Просмотр исходного кода

Merge branch 'release' into project-jp

# Conflicts:
#	src/main/java/com/fdkankan/scene/generate/AutoGenerate.java
#	src/main/java/com/fdkankan/scene/service/impl/SceneProServiceImpl.java
dsx 2 лет назад
Родитель
Сommit
77947384f1
54 измененных файлов с 1916 добавлено и 185 удалено
  1. 12 0
      pom.xml
  2. 11 0
      src/main/java/com/fdkankan/scene/bean/SceneBean.java
  3. 10 0
      src/main/java/com/fdkankan/scene/bean/SceneJsonBean.java
  4. 51 0
      src/main/java/com/fdkankan/scene/config/ScheduledConfig.java
  5. 0 45
      src/main/java/com/fdkankan/scene/config/Test.java
  6. 21 0
      src/main/java/com/fdkankan/scene/controller/SceneCleanOrigController.java
  7. 21 0
      src/main/java/com/fdkankan/scene/controller/SceneColdStorageLogController.java
  8. 55 42
      src/main/java/com/fdkankan/scene/controller/SceneEditController.java
  9. 69 0
      src/main/java/com/fdkankan/scene/entity/SceneCleanOrig.java
  10. 72 0
      src/main/java/com/fdkankan/scene/entity/SceneColdStorage.java
  11. 75 0
      src/main/java/com/fdkankan/scene/entity/SceneColdStorageLog.java
  12. 24 0
      src/main/java/com/fdkankan/scene/entity/SceneEditControls.java
  13. 12 0
      src/main/java/com/fdkankan/scene/entity/SceneEditInfoExt.java
  14. 18 0
      src/main/java/com/fdkankan/scene/mapper/ISceneCleanOrigMapper.java
  15. 18 0
      src/main/java/com/fdkankan/scene/mapper/ISceneColdStorageLogMapper.java
  16. 18 0
      src/main/java/com/fdkankan/scene/mapper/ISceneColdStorageMapper.java
  17. 13 0
      src/main/java/com/fdkankan/scene/mapper/IScenePlusMapper.java
  18. 15 0
      src/main/java/com/fdkankan/scene/mapper/ISceneProMapper.java
  19. 163 0
      src/main/java/com/fdkankan/scene/schedule/ScheduleJob.java
  20. 5 0
      src/main/java/com/fdkankan/scene/service/ICameraService.java
  21. 32 0
      src/main/java/com/fdkankan/scene/service/ISceneCleanOrigService.java
  22. 16 0
      src/main/java/com/fdkankan/scene/service/ISceneColdStorageLogService.java
  23. 18 0
      src/main/java/com/fdkankan/scene/service/ISceneColdStorageService.java
  24. 13 0
      src/main/java/com/fdkankan/scene/service/ISceneEditInfoExtService.java
  25. 3 7
      src/main/java/com/fdkankan/scene/service/ISceneEditInfoService.java
  26. 11 0
      src/main/java/com/fdkankan/scene/service/IScenePlusService.java
  27. 11 0
      src/main/java/com/fdkankan/scene/service/ISceneProService.java
  28. 11 0
      src/main/java/com/fdkankan/scene/service/impl/CameraServiceImpl.java
  29. 306 0
      src/main/java/com/fdkankan/scene/service/impl/SceneCleanOrigServiceImpl.java
  30. 33 0
      src/main/java/com/fdkankan/scene/service/impl/SceneColdStorageLogServiceImpl.java
  31. 36 0
      src/main/java/com/fdkankan/scene/service/impl/SceneColdStorageServiceImpl.java
  32. 380 4
      src/main/java/com/fdkankan/scene/service/impl/SceneEditInfoExtServiceImpl.java
  33. 63 42
      src/main/java/com/fdkankan/scene/service/impl/SceneEditInfoServiceImpl.java
  34. 3 3
      src/main/java/com/fdkankan/scene/service/impl/SceneEditServiceImpl.java
  35. 36 5
      src/main/java/com/fdkankan/scene/service/impl/ScenePlusServiceImpl.java
  36. 34 2
      src/main/java/com/fdkankan/scene/service/impl/SceneProServiceImpl.java
  37. 1 1
      src/main/java/com/fdkankan/scene/service/impl/SceneServiceImpl.java
  38. 8 4
      src/main/java/com/fdkankan/scene/service/impl/SceneUploadServiceImpl.java
  39. 12 0
      src/main/java/com/fdkankan/scene/service/impl/SurveillanceServiceImpl.java
  40. 29 0
      src/main/java/com/fdkankan/scene/vo/BaseJsonArrayParamVO.java
  41. 23 0
      src/main/java/com/fdkankan/scene/vo/DeleteSidListParamVO.java
  42. 1 4
      src/main/java/com/fdkankan/scene/vo/DeleteLinkSceneStylesParamVO.java
  43. 20 0
      src/main/java/com/fdkankan/scene/vo/SceneEditControlsParamVO.java
  44. 19 0
      src/main/java/com/fdkankan/scene/vo/SceneEditControlsVO.java
  45. 6 0
      src/main/java/com/fdkankan/scene/vo/SceneEditInfoParamVO.java
  46. 10 0
      src/main/java/com/fdkankan/scene/vo/SceneInfoVO.java
  47. 1 1
      src/main/resources/bootstrap-prod-eur.yml
  48. 1 0
      src/main/resources/bootstrap-test.yml
  49. 5 0
      src/main/resources/mapper/scene/SceneCleanOrigMapper.xml
  50. 5 0
      src/main/resources/mapper/scene/SceneColdStorageLogMapper.xml
  51. 5 0
      src/main/resources/mapper/scene/SceneColdStorageMapper.xml
  52. 42 1
      src/main/resources/mapper/scene/ScenePlusMapper.xml
  53. 39 1
      src/main/resources/mapper/scene/SceneProMapper.xml
  54. 0 23
      src/test/java/com/fdkankan/scene/SceneApplicationTests.java

+ 12 - 0
pom.xml

@@ -54,6 +54,18 @@
             <groupId>com.fdkankan</groupId>
             <artifactId>4dkankan-common-web</artifactId>
             <version>3.0.0-SNAPSHOT</version>
+            <exclusions>
+                <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>

+ 11 - 0
src/main/java/com/fdkankan/scene/bean/SceneBean.java

@@ -0,0 +1,11 @@
+package com.fdkankan.scene.bean;
+
+import lombok.Data;
+
+@Data
+public class SceneBean {
+
+    private String num;
+
+    private String dataSource;
+}

+ 10 - 0
src/main/java/com/fdkankan/scene/bean/SceneJsonBean.java

@@ -208,5 +208,15 @@ public class SceneJsonBean {
      */
     private Integer surveillances;
 
+    /**
+     * 分享信息
+     */
+    private JSONObject sns;
+
+    /**
+     * 是否有指示牌(0-否,1-是)
+     */
+    private Integer billboards;
+
 
 }

+ 51 - 0
src/main/java/com/fdkankan/scene/config/ScheduledConfig.java

@@ -0,0 +1,51 @@
+package com.fdkankan.scene.config;
+
+import org.springframework.boot.autoconfigure.batch.BatchProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.TaskScheduler;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+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));
+        }
+    }
+}

+ 0 - 45
src/main/java/com/fdkankan/scene/config/Test.java

@@ -1,45 +0,0 @@
-package com.fdkankan.scene.config;
-
-/**
- * <p>
- *  这是一个测试类
- * </p>
- *
- * @author dengsixing
- * @date 2022/1/12
- **/
-public class Test {
-
-    /**
-     * 这是一个类属性
-     */
-    private static final String TEST = "test";
-
-
-    /**
-     * <p>
-     *   这是一个测试方法
-     * </p>
-     * @author dengsixing
-     * @date 2022/1/12
-     * @param id 主键id
-     * @param name  姓名
-     * @return java.lang.String
-     **/
-    public String test(long id, String name){
-        return id + "-" + name;
-    }
-
-    public static void main(String[] args) {
-
-        //方法体内的单行注释
-        String test =  Test.TEST;
-
-        /*
-          方法体内多行注释
-         */
-        String test1 = new Test().test(1, "zhangsan");
-        System.out.println(test1);
-
-    }
-}

+ 21 - 0
src/main/java/com/fdkankan/scene/controller/SceneCleanOrigController.java

@@ -0,0 +1,21 @@
+package com.fdkankan.scene.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 删除oss原始资源记录 前端控制器
+ * </p>
+ *
+ * @author 
+ * @since 2023-03-29
+ */
+@RestController
+@RequestMapping("/scene/sceneCleanOrig")
+public class SceneCleanOrigController {
+
+}
+

+ 21 - 0
src/main/java/com/fdkankan/scene/controller/SceneColdStorageLogController.java

@@ -0,0 +1,21 @@
+package com.fdkankan.scene.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 场景冷归档日志表 前端控制器
+ * </p>
+ *
+ * @author 
+ * @since 2023-07-12
+ */
+@RestController
+@RequestMapping("/scene/sceneColdStorageLog")
+public class SceneColdStorageLogController {
+
+}
+

+ 55 - 42
src/main/java/com/fdkankan/scene/controller/SceneEditController.java

@@ -3,48 +3,9 @@ package com.fdkankan.scene.controller;
 import com.fdkankan.common.constant.ErrorCode;
 import com.fdkankan.common.constant.SceneInfoReqType;
 import com.fdkankan.common.exception.BusinessException;
-import com.fdkankan.model.utils.CreateHouseJsonUtil;
 import com.fdkankan.scene.annotation.CheckPermit;
-import com.fdkankan.scene.entity.SceneAsynOperLog;
-import com.fdkankan.scene.service.IBoxModelService;
-import com.fdkankan.scene.service.IDownloadTourVideoService;
-import com.fdkankan.scene.service.ISceneAsynOperLogService;
-import com.fdkankan.scene.service.ISceneEditInfoService;
-import com.fdkankan.scene.service.ISceneEditService;
-import com.fdkankan.scene.service.IScenePlusService;
-import com.fdkankan.scene.service.ISceneProService;
-import com.fdkankan.scene.service.ISceneUploadService;
-import com.fdkankan.scene.service.ISurveillanceService;
-import com.fdkankan.scene.vo.BallScreenVideoParamVO;
-import com.fdkankan.scene.vo.BaseDataParamVO;
-import com.fdkankan.scene.vo.BaseFileParamVO;
-import com.fdkankan.scene.vo.BaseJsonDataParamVO;
-import com.fdkankan.scene.vo.BaseSceneParamVO;
-import com.fdkankan.scene.vo.BaseSidParamVO;
-import com.fdkankan.scene.vo.DeleteFileParamVO;
-import com.fdkankan.scene.vo.DeleteHotIconParamVO;
-import com.fdkankan.scene.vo.DeleteHotParamVO;
-import com.fdkankan.scene.vo.DeleteLinkPanParamVO;
-import com.fdkankan.scene.vo.DeleteLinkSceneStylesParamVO;
-import com.fdkankan.scene.vo.DeleteMosaicParamVO;
-import com.fdkankan.scene.vo.DeleteSidParamVO;
-import com.fdkankan.scene.vo.DownloadVO;
-import com.fdkankan.scene.vo.FileNameAndDataParamVO;
-import com.fdkankan.scene.vo.FileParamVO;
-import com.fdkankan.scene.vo.LocalesParamVO;
-import com.fdkankan.scene.vo.RenameCadParamVO;
-import com.fdkankan.scene.vo.SaveFiltersParamVO;
-import com.fdkankan.scene.vo.SaveLinkPanParamVO;
-import com.fdkankan.scene.vo.SaveTagsParamVO;
-import com.fdkankan.scene.vo.SaveTagsVisibleParamVO;
-import com.fdkankan.scene.vo.SceneAsynOperLogParamVO;
-import com.fdkankan.scene.vo.SceneAuthVO;
-import com.fdkankan.scene.vo.SceneEditInfoParamVO;
-import com.fdkankan.scene.vo.SceneEditInfoVO;
-import com.fdkankan.scene.vo.SceneInfoParamVO;
-import com.fdkankan.scene.vo.SceneInfoVO;
-import com.fdkankan.scene.vo.SurveillanceParamVO;
-import com.fdkankan.scene.vo.UploadContentParamVO;
+import com.fdkankan.scene.service.*;
+import com.fdkankan.scene.vo.*;
 import com.fdkankan.web.controller.BaseController;
 import com.fdkankan.web.response.ResultData;
 import java.io.IOException;
@@ -90,6 +51,8 @@ public class SceneEditController extends BaseController {
     private IScenePlusService scenePlusService;
     @Autowired
     private ISceneAsynOperLogService sceneAsynOperLogService;
+    @Autowired
+    private ISceneEditInfoExtService sceneEditInfoExtService;
 
     /**
      * <p>
@@ -319,7 +282,7 @@ public class SceneEditController extends BaseController {
      **/
     @CheckPermit
     @PostMapping(value = "/styles/delete")
-    public ResultData deleteStyles(@RequestBody @Validated DeleteLinkSceneStylesParamVO param) throws Exception {
+    public ResultData deleteStyles(@RequestBody @Validated DeleteStylesParamVO param) throws Exception {
         return sceneEditInfoService.deleteStyles(param);
     }
 
@@ -887,4 +850,54 @@ public class SceneEditController extends BaseController {
         return sceneEditService.getServiceUpTip();
     }
 
+    /**
+     * 保存或者修改指示牌
+     * @param param
+     * @return
+     * @throws Exception
+     */
+    @CheckPermit
+    @PostMapping("/billboards/save")
+    public ResultData saveBillboards(@RequestBody @Validated BaseJsonArrayParamVO param) throws Exception {
+        return sceneEditInfoExtService.saveBillboards(param);
+    }
+
+    /**
+     * 删除指示牌
+     * @param param
+     * @return
+     * @throws Exception
+     */
+    @CheckPermit
+    @PostMapping("/billboards/delete")
+    public ResultData deleteBillboards(@RequestBody @Validated DeleteSidListParamVO param) throws Exception {
+        return sceneEditInfoExtService.deleteBillboards(param);
+    }
+
+    /**
+     * 获取指示牌列表
+     * @param param
+     * @return
+     * @throws Exception
+     */
+    @CheckPermit
+    @PostMapping("/billboards/list")
+    public ResultData deleteBillboards(@RequestBody @Validated BaseSceneParamVO param) throws Exception {
+        return ResultData.ok(sceneEditInfoExtService.listBillboards(param));
+    }
+
+    /**
+     * 获取指示牌列表
+     * @param param
+     * @return
+     * @throws Exception
+     */
+    @CheckPermit
+    @PostMapping("/billboards/styles/delete")
+    public ResultData deleteBillboards(@RequestBody @Validated DeleteStylesParamVO param) throws Exception {
+        return ResultData.ok(sceneEditInfoExtService.deleteBillboardsStyles(param));
+    }
+
+
+
 }

+ 69 - 0
src/main/java/com/fdkankan/scene/entity/SceneCleanOrig.java

@@ -0,0 +1,69 @@
+package com.fdkankan.scene.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 删除oss原始资源记录
+ * </p>
+ *
+ * @author 
+ * @since 2023-03-29
+ */
+@Getter
+@Setter
+@TableName("t_scene_clean_orig")
+public class SceneCleanOrig implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @TableField("num")
+    private String num;
+
+    /**
+     * type
+     */
+    @TableField("type")
+    private Integer type;
+
+    /**
+     * 0-处理中,1-成功,-1失败
+     */
+    @TableField("state")
+    private Integer state;
+
+    /**
+     * 失败原因
+     */
+    @TableField("reason")
+    private String reason;
+
+    /**
+     * 创建时间
+     */
+    @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;
+
+
+}

+ 72 - 0
src/main/java/com/fdkankan/scene/entity/SceneColdStorage.java

@@ -0,0 +1,72 @@
+package com.fdkankan.scene.entity;
+
+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 2023-07-25
+ */
+@Getter
+@Setter
+@TableName("t_scene_cold_storage")
+public class SceneColdStorage implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 场景码
+     */
+    @TableField("num")
+    private String num;
+
+    /**
+     * 1-封存,2-未封存
+     */
+    @TableField("state")
+    private Integer state;
+
+    /**
+     * 创建时间
+     */
+    @TableField("create_time")
+    private Date createTime;
+
+    /**
+     * 修改时间
+     */
+    @TableField("update_time")
+    private Date updateTime;
+
+    @TableField("rec_status")
+    @TableLogic(value = "A", delval = "I")
+    private String recStatus;
+
+    /**
+     * 冷存储bucket
+     */
+    @TableField("cold_bucket")
+    private String coldBucket;
+
+    /**
+     * 正常使用bucket
+     */
+    @TableField("bucket")
+    private String bucket;
+
+
+}

+ 75 - 0
src/main/java/com/fdkankan/scene/entity/SceneColdStorageLog.java

@@ -0,0 +1,75 @@
+package com.fdkankan.scene.entity;
+
+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 2023-07-12
+ */
+@Getter
+@Setter
+@TableName("t_scene_cold_storage_log")
+public class SceneColdStorageLog implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 场景码
+     */
+    @TableField("num")
+    private String num;
+
+    /**
+     * 封存地址
+     */
+    @TableField("path")
+    private String path;
+
+    /**
+     * 操作类型(1-封存,2-解封存)
+     */
+    @TableField("type")
+    private Integer type;
+
+    @TableField("state")
+    private Integer state;
+
+    @TableField("reason")
+    private String reason;
+
+    /**
+     * 创建时间
+     */
+    @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;
+
+
+}

+ 24 - 0
src/main/java/com/fdkankan/scene/entity/SceneEditControls.java

@@ -113,6 +113,30 @@ public class SceneEditControls implements Serializable {
     @TableField("show_capture")
     private Integer showCapture;
 
+    /**
+     * 是否显示多媒体标签标题(0-否,1-是)
+     */
+    @TableField("show_tag_title")
+    private Integer showTagTitle;
+
+    /**
+     * 是否显示指示牌标签标题(0-否,1-是)
+     */
+    @TableField("show_billboard_title")
+    private Integer showBillboardTitle;
+
+    /**
+     * 是否显示视频监控标签标题(0-否,1-是)
+     */
+    @TableField("show_camera_title")
+    private Integer showCameraTitle;
+
+    /**
+     * 是否显示场景关联标签标题(0-否,1-是)
+     */
+    @TableField("show_link_title")
+    private Integer showLinkTitle;
+
 
     /**
      * 创建时间

+ 12 - 0
src/main/java/com/fdkankan/scene/entity/SceneEditInfoExt.java

@@ -91,6 +91,18 @@ public class SceneEditInfoExt {
     private String shareLogoImg;
 
     /**
+     * 是否有指示牌(0-否,1-是)
+     */
+    @TableField("billboards")
+    private Integer billboards;
+
+    /**
+     * 分享配置信息
+     */
+    @TableField("sns_info")
+    private String snsInfo;
+
+    /**
      * 创建时间
      */
     @TableField("create_time")

+ 18 - 0
src/main/java/com/fdkankan/scene/mapper/ISceneCleanOrigMapper.java

@@ -0,0 +1,18 @@
+package com.fdkankan.scene.mapper;
+
+import com.fdkankan.scene.entity.SceneCleanOrig;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 删除oss原始资源记录 Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2023-03-29
+ */
+@Mapper
+public interface ISceneCleanOrigMapper extends BaseMapper<SceneCleanOrig> {
+
+}

+ 18 - 0
src/main/java/com/fdkankan/scene/mapper/ISceneColdStorageLogMapper.java

@@ -0,0 +1,18 @@
+package com.fdkankan.scene.mapper;
+
+import com.fdkankan.scene.entity.SceneColdStorageLog;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 场景冷归档日志表 Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2023-07-12
+ */
+@Mapper
+public interface ISceneColdStorageLogMapper extends BaseMapper<SceneColdStorageLog> {
+
+}

+ 18 - 0
src/main/java/com/fdkankan/scene/mapper/ISceneColdStorageMapper.java

@@ -0,0 +1,18 @@
+package com.fdkankan.scene.mapper;
+
+import com.fdkankan.scene.entity.SceneColdStorage;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 场景封存状态表 Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2023-07-25
+ */
+@Mapper
+public interface ISceneColdStorageMapper extends BaseMapper<SceneColdStorage> {
+
+}

+ 13 - 0
src/main/java/com/fdkankan/scene/mapper/IScenePlusMapper.java

@@ -1,9 +1,14 @@
 package com.fdkankan.scene.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fdkankan.scene.bean.SceneBean;
 import com.fdkankan.scene.entity.ScenePlus;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
 /**
  * <p>
  * 场景主表 Mapper 接口
@@ -15,4 +20,12 @@ import org.apache.ibatis.annotations.Mapper;
 @Mapper
 public interface IScenePlusMapper extends BaseMapper<ScenePlus> {
 
+    List<SceneBean> selectCleanOrigScene(Date time);
+
+    List<SceneBean> selectCleanOrigSceneDeleted(Date time);
+
+    List<SceneBean> listCleanOss4TestCamera(Set<Long> cameraIds, Date time);
+
+    List<SceneBean> selectColdStorageScene(Date time);
+
 }

+ 15 - 0
src/main/java/com/fdkankan/scene/mapper/ISceneProMapper.java

@@ -1,9 +1,14 @@
 package com.fdkankan.scene.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fdkankan.scene.bean.SceneBean;
 import com.fdkankan.scene.entity.ScenePro;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
 /**
  * <p>
  * pro场景表 Mapper 接口
@@ -15,4 +20,14 @@ import org.apache.ibatis.annotations.Mapper;
 @Mapper
 public interface ISceneProMapper extends BaseMapper<ScenePro> {
 
+    List<SceneBean> selectCleanOrigScene(Date time);
+
+    List<SceneBean> listCleanOss4DeletedScene(Date time);
+
+    List<SceneBean> listCleanOss4TestCamera(Set<Long> cameraIds, Date time);
+
+    List<SceneBean> selectColdStorageScene(Date time);
+
+
+
 }

+ 163 - 0
src/main/java/com/fdkankan/scene/schedule/ScheduleJob.java

@@ -1,19 +1,32 @@
 package com.fdkankan.scene.schedule;
 
+import com.fdkankan.redis.constant.RedisLockKey;
+import com.fdkankan.redis.util.RedisLockUtil;
 import com.fdkankan.scene.service.ISceneAsynOperLogService;
+import com.fdkankan.scene.service.ISceneCleanOrigService;
 import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.cloud.context.config.annotation.RefreshScope;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
+import javax.annotation.PostConstruct;
+
 @RefreshScope
 @Log4j2
 @Component
 public class ScheduleJob {
 
+    @Value("${environment:#{null}}")
+    private String environment;
+
     @Autowired
     private ISceneAsynOperLogService sceneAsynOperLogService;
+    @Autowired
+    private ISceneCleanOrigService sceneCleanOrigService;
+    @Autowired
+    private RedisLockUtil redisLockUtil;
 
     /**
      * 每天凌晨一点执行
@@ -24,4 +37,154 @@ public class ScheduleJob {
         sceneAsynOperLogService.cleanDownloadPanorama();
         log.info("定时清除全景图压缩包完毕");
     }
+
+//    /**
+//     * 删除场景原始资源
+//     * 每天凌晨执行
+//     */
+//    @Scheduled(cron="0 0 1 * * ?")
+//    public void cleanOssHomeV3() {
+//        log.info("删除v3场景原始资源开始");
+//        String lockKey = RedisLockKey.LOCK_CLEAN_SCENE_ORIG_V3;
+//        try {
+//            boolean lock = redisLockUtil.lock(lockKey, 24*60*60);
+//            if(!lock){
+//                return;
+//            }
+//            sceneCleanOrigService.cleanOrigV3();
+//        }finally {
+//            redisLockUtil.unlockLua(lockKey);
+//        }
+//        log.info("删除v3场景原始资源结束");
+//    }
+//
+//    /**
+//     * 删除场景原始资源
+//     * 每天凌晨执行
+//     */
+//    @Scheduled(cron="0 0 1 * * ?")
+//    public void cleanOssHomeV4() {
+//        log.info("删除v4场景原始资源开始");
+//        String lockKey = RedisLockKey.LOCK_CLEAN_SCENE_ORIG_V4;
+//        try {
+//            boolean lock = redisLockUtil.lock(lockKey, 24*60*60);
+//            if(!lock){
+//                return;
+//            }
+//            sceneCleanOrigService.cleanOrigV4();
+//        }finally {
+//            redisLockUtil.unlockLua(lockKey);
+//        }
+//        log.info("删除v4场景原始资源结束");
+//    }
+
+    /**
+     * 删除已删除场景原始资源及caches
+     * 每天凌晨执行
+     */
+    @Scheduled(cron="0 0 1 * * ?")
+    public void cleanOss4DeletedSceneV3() {
+        log.info("删除已删除V3场景原始资源开始");
+        String lockKey = RedisLockKey.LOCK_CLEAN_SCENE_DELETED_ORIG_V3;
+        try {
+            boolean lock = redisLockUtil.lock(lockKey, 24*60*60);
+            if(!lock){
+                return;
+            }
+            sceneCleanOrigService.cleanOss4DeletedSceneV3();
+        }finally {
+            redisLockUtil.unlockLua(lockKey);
+        }
+        log.info("删除已删除V3场景原始资源结束");
+    }
+
+
+    /**
+     * 删除已删除场景原始资源及caches
+     * 每天凌晨执行
+     */
+    @Scheduled(cron="0 0 1 * * ?")
+    public void cleanOss4DeletedSceneV4() {
+        log.info("删除已删除V4场景原始资源开始");
+        String lockKey = RedisLockKey.LOCK_CLEAN_SCENE_DELETED_ORIG_V4;
+        try {
+            boolean lock = redisLockUtil.lock(lockKey, 24*60*60);
+            if(!lock){
+                return;
+            }
+            sceneCleanOrigService.cleanOss4DeletedSceneV4();
+        }finally {
+            redisLockUtil.unlockLua(lockKey);
+        }
+        log.info("删除已删除V4场景原始资源结束");
+    }
+
+//    /**
+//     * 删除测试相机场景原始资源及caches
+//     * 每天凌晨执行
+//     */
+//    @Scheduled(cron="0 0 1 * * ?")
+//    public void cleanOss4TestCameraV3() {
+//        if(StrUtil.isEmpty(environment) || !environment.equals("dev")){
+//            return;
+//        }
+//        log.info("删除已删除V4场景原始资源开始");
+//        sceneCleanOrigService.cleanOss4TestCameraV3();
+//        log.info("删除已删除V4场景原始资源结束");
+//    }
+//
+//
+//    /**
+//     * 删除测试相机场景原始资源及caches
+//     * 每天凌晨执行
+//     */
+//    @Scheduled(cron="0 0 1 * * ?")
+//    public void cleanOss4TestCameraV4() {
+//        if(StrUtil.isEmpty(environment) || !environment.equals("dev")){
+//            return;
+//        }
+//        log.info("删除已删除V4场景原始资源开始");
+//        sceneCleanOrigService.cleanOss4TestCameraV4();
+//        log.info("删除已删除V4场景原始资源结束");
+//    }
+
+    /**
+     * 删除场景原始资源
+     * 每天凌晨执行
+     */
+    @Scheduled(cron="0 0 1 * * ?")
+    public void coldStorageHomeV3() {
+        log.info("冻结v3场景原始资源开始");
+        String lockKey = RedisLockKey.LOCK_CLEAN_SCENE_ORIG_V3;
+        try {
+            boolean lock = redisLockUtil.lock(lockKey, 24*60*60);
+            if(!lock){
+                return;
+            }
+            sceneCleanOrigService.coldStorageHomeV3();
+        }finally {
+            redisLockUtil.unlockLua(lockKey);
+        }
+        log.info("冻结v3场景原始资源结束");
+    }
+
+    /**
+     * 删除场景原始资源
+     * 每天凌晨执行
+     */
+    @Scheduled(cron="0 0 1 * * ?")
+    public void coldStorageHomeV4() {
+        log.info("冻结v4场景原始资源开始");
+        String lockKey = RedisLockKey.LOCK_CLEAN_SCENE_ORIG_V4;
+        try {
+            boolean lock = redisLockUtil.lock(lockKey, 24*60*60);
+            if(!lock){
+                return;
+            }
+            sceneCleanOrigService.coldStorageHomeV4();
+        }finally {
+            redisLockUtil.unlockLua(lockKey);
+        }
+        log.info("冻结v4场景原始资源结束");
+    }
 }

+ 5 - 0
src/main/java/com/fdkankan/scene/service/ICameraService.java

@@ -3,6 +3,8 @@ package com.fdkankan.scene.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fdkankan.scene.entity.Camera;
 
+import java.util.List;
+
 /**
  * <p>
  * 相机主表 服务类
@@ -15,4 +17,7 @@ public interface ICameraService extends IService<Camera> {
 
     Camera findByChildName(String childName);
 
+    List<Camera> listBySnCodes(List<String> snCodes);
+
+
 }

+ 32 - 0
src/main/java/com/fdkankan/scene/service/ISceneCleanOrigService.java

@@ -0,0 +1,32 @@
+package com.fdkankan.scene.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.scene.entity.SceneCleanOrig;
+
+/**
+ * <p>
+ * 删除oss原始资源记录 服务类
+ * </p>
+ *
+ * @author 
+ * @since 2023-03-29
+ */
+public interface ISceneCleanOrigService extends IService<SceneCleanOrig> {
+
+    void cleanOrigV3();
+
+    void cleanOrigV4();
+
+    void cleanOss4DeletedSceneV3();
+
+    void cleanOss4DeletedSceneV4();
+
+    void cleanOss4TestCameraV3();
+
+    void cleanOss4TestCameraV4();
+
+    void coldStorageHomeV3();
+
+    void coldStorageHomeV4();
+
+}

+ 16 - 0
src/main/java/com/fdkankan/scene/service/ISceneColdStorageLogService.java

@@ -0,0 +1,16 @@
+package com.fdkankan.scene.service;
+
+import com.fdkankan.scene.entity.SceneColdStorageLog;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 场景冷归档日志表 服务类
+ * </p>
+ *
+ * @author 
+ * @since 2023-07-12
+ */
+public interface ISceneColdStorageLogService extends IService<SceneColdStorageLog> {
+    void saveLog(String num, String path, Integer type, Integer state, String reason);
+}

+ 18 - 0
src/main/java/com/fdkankan/scene/service/ISceneColdStorageService.java

@@ -0,0 +1,18 @@
+package com.fdkankan.scene.service;
+
+import com.fdkankan.scene.entity.SceneColdStorage;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 场景封存状态表 服务类
+ * </p>
+ *
+ * @author 
+ * @since 2023-07-25
+ */
+public interface ISceneColdStorageService extends IService<SceneColdStorage> {
+
+    void save(String num, Integer state, String coldBucket, String standarBucket);
+
+}

+ 13 - 0
src/main/java/com/fdkankan/scene/service/ISceneEditInfoExtService.java

@@ -1,7 +1,12 @@
 package com.fdkankan.scene.service;
 
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fdkankan.scene.entity.SceneEditInfoExt;
+import com.fdkankan.scene.vo.*;
+import com.fdkankan.web.response.ResultData;
+
+import java.util.List;
 
 /**
  * <p>
@@ -19,4 +24,12 @@ public interface ISceneEditInfoExtService extends IService<SceneEditInfoExt> {
 
     void updateToursByNum(String num, Integer tours);
 
+    ResultData saveBillboards(BaseJsonArrayParamVO param) throws Exception;
+
+    ResultData deleteBillboards(DeleteSidListParamVO param) throws Exception;
+
+    JSONObject listBillboards(BaseSceneParamVO param) throws Exception;
+
+    ResultData deleteBillboardsStyles(DeleteStylesParamVO param) throws Exception;
+
 }

+ 3 - 7
src/main/java/com/fdkankan/scene/service/ISceneEditInfoService.java

@@ -2,17 +2,15 @@ package com.fdkankan.scene.service;
 
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.fdkankan.scene.annotation.CheckPermit;
 import com.fdkankan.scene.vo.BaseSceneParamVO;
 import com.fdkankan.scene.vo.SaveFiltersParamVO;
-import com.fdkankan.scene.vo.SurveillanceParamVO;
 import com.fdkankan.web.response.ResultData;
 import com.fdkankan.scene.entity.SceneEditInfo;
 import com.fdkankan.scene.vo.BallScreenVideoParamVO;
 import com.fdkankan.scene.vo.BaseDataParamVO;
 import com.fdkankan.scene.vo.BaseFileParamVO;
 import com.fdkankan.scene.vo.DeleteLinkPanParamVO;
-import com.fdkankan.scene.vo.DeleteLinkSceneStylesParamVO;
+import com.fdkankan.scene.vo.DeleteStylesParamVO;
 import com.fdkankan.scene.vo.DeleteMosaicParamVO;
 import com.fdkankan.scene.vo.DeleteSidParamVO;
 import com.fdkankan.scene.vo.DownloadVO;
@@ -27,9 +25,7 @@ import com.fdkankan.scene.vo.SceneInfoParamVO;
 import com.fdkankan.scene.vo.SceneInfoVO;
 import java.io.IOException;
 import java.util.List;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
+
 import org.springframework.web.multipart.MultipartFile;
 
 /**
@@ -100,7 +96,7 @@ public interface ISceneEditInfoService extends IService<SceneEditInfo> {
 
     ResultData deleteLinkPan(DeleteLinkPanParamVO param) throws Exception;
 
-    ResultData deleteStyles(DeleteLinkSceneStylesParamVO param) throws Exception;
+    ResultData deleteStyles(DeleteStylesParamVO param) throws Exception;
 
     ResultData deleteMosaics(DeleteMosaicParamVO param) throws Exception;
 

+ 11 - 0
src/main/java/com/fdkankan/scene/service/IScenePlusService.java

@@ -1,9 +1,12 @@
 package com.fdkankan.scene.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.scene.bean.SceneBean;
 import com.fdkankan.web.response.ResultData;
 import com.fdkankan.scene.vo.BaseSceneParamVO;
 import java.util.List;
+import java.util.Set;
+
 import com.fdkankan.scene.entity.ScenePlus;
 import com.fdkankan.scene.vo.SceneCheckKeyParamVO;
 import org.springframework.web.multipart.MultipartFile;
@@ -34,4 +37,12 @@ public interface IScenePlusService extends IService<ScenePlus> {
 
     ResultData uploadShareLogo(String num, MultipartFile file) throws Exception;
 
+    List<SceneBean> listCleanOrigScene(int cleanOrigMonth);
+
+    List<SceneBean> listCleanOss4DeletedScene(int cleanOrigMonth);
+
+    List<SceneBean> listCleanOss4TestCamera(Set<Long> cameraIds, int cleanOrigMonth);
+
+    List<SceneBean> listColdStorageScene(int month);
+
 }

+ 11 - 0
src/main/java/com/fdkankan/scene/service/ISceneProService.java

@@ -1,6 +1,7 @@
 package com.fdkankan.scene.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.scene.bean.SceneBean;
 import com.fdkankan.web.response.ResultData;
 import com.fdkankan.scene.entity.ScenePro;
 import com.fdkankan.scene.vo.BaseDataParamVO;
@@ -14,6 +15,8 @@ import com.fdkankan.scene.vo.SceneEditParamVO;
 import com.fdkankan.scene.vo.SceneParamVO;
 import com.fdkankan.scene.vo.SceneVO;
 import java.util.List;
+import java.util.Set;
+
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -49,4 +52,12 @@ public interface ISceneProService extends IService<ScenePro> {
 
     ScenePro getByNum(String num);
 
+    List<SceneBean> listCleanOrigScene(int cleanOrigMonth);
+
+    List<SceneBean> listCleanOss4DeletedScene(int month);
+
+    List<SceneBean> listCleanOss4TestCamera(Set<Long> cameraIds, int month);
+
+    List<SceneBean> listColdStorageScene(int month);
+
 }

+ 11 - 0
src/main/java/com/fdkankan/scene/service/impl/CameraServiceImpl.java

@@ -1,5 +1,6 @@
 package com.fdkankan.scene.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fdkankan.scene.entity.Camera;
@@ -7,6 +8,8 @@ import com.fdkankan.scene.mapper.ICameraMapper;
 import com.fdkankan.scene.service.ICameraService;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 /**
  * <p>
  * 相机主表 服务实现类
@@ -22,4 +25,12 @@ public class CameraServiceImpl extends ServiceImpl<ICameraMapper, Camera> implem
     public Camera findByChildName(String childName) {
         return this.getOne(new LambdaQueryWrapper<Camera>().eq(Camera::getChildName, childName));
     }
+
+    @Override
+    public List<Camera> listBySnCodes(List<String> snCodes) {
+        if(CollUtil.isEmpty(snCodes)){
+            return null;
+        }
+        return this.list(new LambdaQueryWrapper<Camera>().in(Camera::getSnCode, snCodes));
+    }
 }

+ 306 - 0
src/main/java/com/fdkankan/scene/service/impl/SceneCleanOrigServiceImpl.java

@@ -0,0 +1,306 @@
+package com.fdkankan.scene.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.exceptions.ExceptionUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.fdkankan.common.constant.CommonStatus;
+import com.fdkankan.common.constant.CommonSuccessStatus;
+import com.fdkankan.common.constant.ErrorCode;
+import com.fdkankan.common.constant.OperationType;
+import com.fdkankan.common.exception.BusinessException;
+import com.fdkankan.fyun.config.FYunFileConfig;
+import com.fdkankan.fyun.constant.FYunTypeEnum;
+import com.fdkankan.fyun.face.FYunFileServiceInterface;
+import com.fdkankan.model.constants.ConstantFilePath;
+import com.fdkankan.model.constants.UploadFilePath;
+import com.fdkankan.model.utils.SceneUtil;
+import com.fdkankan.redis.constant.RedisKey;
+import com.fdkankan.redis.util.RedisUtil;
+import com.fdkankan.scene.bean.SceneBean;
+import com.fdkankan.scene.entity.Camera;
+import com.fdkankan.scene.entity.SceneCleanOrig;
+import com.fdkankan.scene.mapper.ISceneCleanOrigMapper;
+import com.fdkankan.scene.mapper.IScenePlusExtMapper;
+import com.fdkankan.scene.service.*;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.stereotype.Service;
+import sun.font.TextRecord;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 删除oss原始资源记录 服务实现类
+ * </p>
+ *
+ * @author 
+ * @since 2023-03-29
+ */
+@RefreshScope
+@Slf4j
+@Service
+public class SceneCleanOrigServiceImpl extends ServiceImpl<ISceneCleanOrigMapper, SceneCleanOrig> implements ISceneCleanOrigService {
+
+    @Value("${scene.cleanOrig.month}")
+    private Integer cleanOrigMonth;
+    @Value("${scene.coldStorage.month}")
+    private Integer coldStorageMonth;
+    @Value("${scene.cleanDeleted.month}")
+    private Integer cleanDeletedMonth;
+    @Value("#{'${scene.cleanTestCamera.snCode:}'.split(',')}")
+    private List<String> testSnCodeList;
+    @Value("${scene.cleanTestCamera.month}")
+    private Integer cleanTestCameraMonth;
+    @Value("${fyun.bucket}")
+    private String bucket;
+    @Value("${fyun.coldBucket}")
+    private String coldBucket;
+    @Autowired
+    private ICameraService cameraService;
+    @Autowired
+    private ISceneColdStorageService sceneColdStorageService;
+    @Autowired
+    private FYunFileConfig fYunFileConfig;
+
+
+    @Autowired
+    private ISceneProService sceneProService;
+    @Autowired
+    private IScenePlusService scenePlusService;
+    @Autowired
+    private IScenePlusExtService scenePlusExtService;
+    @Autowired
+    private FYunFileServiceInterface fYunFileService;
+    @Autowired
+    private RedisUtil redisUtil;
+    @Autowired
+    private ISceneColdStorageLogService sceneColdStorageLogService;
+
+    @Override
+    public void cleanOrigV4() {
+        //查询所有计算时间超过限定时间的场景,计算成功、未被删除、最后一次计算后未被删除过的
+        List<SceneBean> sceneBeans = scenePlusService.listCleanOrigScene(cleanOrigMonth);
+        this.cleanOrig(sceneBeans);
+    }
+
+    @Override
+    public void cleanOrigV3() {
+        //查询所有计算时间超过限定时间的场景,计算成功、未被删除
+        List<SceneBean> sceneBeans = sceneProService.listCleanOrigScene(cleanOrigMonth);
+        this.cleanOrig(sceneBeans);
+
+    }
+
+    private void cleanOrig(List<SceneBean> sceneBeans){
+        if(CollUtil.isEmpty(sceneBeans)){
+            return;
+        }
+        sceneBeans.parallelStream().forEach(scene->{
+            boolean lock = this.lock(scene.getDataSource());
+            try {
+                if(lock) {
+                    this.cleanOrigHandler(scene);
+                    this.saveLog(scene.getNum(), 1, CommonSuccessStatus.SUCCESS.code(), null);
+                }
+            }catch (Exception e){
+                log.error("删除原始资源失败,num : " + scene.getNum(), e);
+                this.saveLog(scene.getNum(), 1, CommonSuccessStatus.FAIL.code(), ExceptionUtil.stacktraceToString(e, 3000));
+            }finally {
+                this.releaseLock(scene.getDataSource());
+            }
+        });
+    }
+
+    private void cleanOrigHandler(SceneBean scene){
+        String dataSource = scene.getDataSource();
+        if(StrUtil.isNotEmpty(dataSource)){
+            String homePath = dataSource.replace(ConstantFilePath.BUILD_MODEL_PATH, ConstantFilePath.OSS_PREFIX);
+            //由于国内测试和生产用的bucket是同一个,这里需要做一个安全校验,保证不会删错
+            String fileContent = fYunFileService.getFileContent(homePath.concat("/").concat("data.fdage"));
+            if(StrUtil.isNotBlank(fileContent)){
+                JSONObject jsonObject = JSON.parseObject(fileContent);
+                String snCode = jsonObject.getJSONObject("cam").getString("uuid");
+                String uuidTime = jsonObject.getString("uuidtime");
+                if(StrUtil.isEmpty(snCode)
+                        || StrUtil.isEmpty(uuidTime)
+                        || !homePath.contains(snCode)
+                        || !homePath.contains(uuidTime)){
+                    throw new RuntimeException("dataSource与data.fdage文件不匹配");
+                }else{
+                    fYunFileService.deleteFolder(homePath);
+                }
+            }
+        }
+    }
+
+
+
+
+    private void saveLog(String num, int type, int status, String reason){
+        //清除旧的日志
+        this.remove(new LambdaQueryWrapper<SceneCleanOrig>().eq(SceneCleanOrig::getNum, num));
+        SceneCleanOrig sceneCleanOrig = new SceneCleanOrig();
+        sceneCleanOrig.setNum(num);
+        sceneCleanOrig.setType(type);
+        sceneCleanOrig.setState(status);
+        sceneCleanOrig.setReason(reason);
+        this.saveOrUpdate(sceneCleanOrig);
+    }
+
+    private boolean lock(String dataSource){
+        Map<String, String> property = SceneUtil.getPropertyFromDataSource(dataSource);
+        String homePath = property.get("homePath");
+        String uuid = property.get("uuid");
+
+        String uploadLock = redisUtil.get(String.format(RedisKey.SCENE_OSS_HOME_DIR_UPLOAD, uuid));
+        //场景正在上传,不删除
+        if(StrUtil.isNotEmpty(uploadLock)){
+            return false;
+        }
+        redisUtil.set(String.format(RedisKey.SCENE_OSS_HOME_DIR_DELETE, uuid), homePath, 8*60*60);
+        return true;
+    }
+
+    private void releaseLock(String dataSource){
+        Map<String, String> property = SceneUtil.getPropertyFromDataSource(dataSource);
+        String uuid = property.get("uuid");
+        redisUtil.del(String.format(RedisKey.SCENE_OSS_HOME_DIR_DELETE, uuid));
+    }
+
+
+    @Override
+    public void cleanOss4DeletedSceneV3() {
+        List<SceneBean> sceneBeans = sceneProService.listCleanOss4DeletedScene(cleanDeletedMonth);
+        this.cleanOrig4Delete(sceneBeans, false, 2);
+    }
+
+    @Override
+    public void cleanOss4DeletedSceneV4() {
+        //查询所有计算时间超过限定时间的场景,计算成功、未被删除、最后一次计算后未被删除过的
+        List<SceneBean> sceneBeans = scenePlusService.listCleanOss4DeletedScene(cleanDeletedMonth);
+        this.cleanOrig4Delete(sceneBeans, true, 2);
+    }
+
+    /**
+     * 删除已删除场景的原始资源及caches目录(v3场景不需要删除caches目录)
+     * @param sceneBeans
+     * @param deleteCaches 是否需要删除caches目录
+     */
+    private void cleanOrig4Delete(List<SceneBean> sceneBeans, boolean deleteCaches, Integer type){
+        if(CollUtil.isEmpty(sceneBeans)){
+            return;
+        }
+        sceneBeans.parallelStream().forEach(scene->{
+            try {
+                //删除caches文件
+                if(deleteCaches){
+                    this.deleteResultCaches(scene.getNum());
+                }
+                //删除原始资源
+                this.cleanOrigHandler(scene);
+
+                this.saveLog(scene.getNum(), type, CommonSuccessStatus.SUCCESS.code(), null);
+            }catch (Exception e){
+                log.error("删除已删除场景资源失败,num : " + scene.getNum(), e);
+                this.saveLog(scene.getNum(), type, CommonSuccessStatus.FAIL.code(), ExceptionUtil.stacktraceToString(e, 3000));
+            }
+        });
+    }
+
+    private void deleteResultCaches(String num){
+        String cachesPath = String.format(UploadFilePath.scene_result_data_path, num).concat("caches");
+        if(CollUtil.isEmpty(fYunFileService.listRemoteFiles(cachesPath))){
+            return;
+        }
+        fYunFileService.deleteFolder(cachesPath);
+    }
+
+    @Override
+    public void cleanOss4TestCameraV3() {
+        List<Camera> cameras = cameraService.listBySnCodes(testSnCodeList);
+        if(CollUtil.isEmpty(cameras)){
+            return;
+        }
+        Set<Long> cameraIds = cameras.stream().map(Camera::getId).collect(Collectors.toSet());
+        List<SceneBean> sceneBeans = sceneProService.listCleanOss4TestCamera(cameraIds, cleanTestCameraMonth);
+        this.cleanOrig4Delete(sceneBeans, false, 3);
+    }
+
+    @Override
+    public void cleanOss4TestCameraV4() {
+        List<Camera> cameras = cameraService.listBySnCodes(testSnCodeList);
+        if(CollUtil.isEmpty(cameras)){
+            return;
+        }
+        Set<Long> cameraIds = cameras.stream().map(Camera::getId).collect(Collectors.toSet());
+        List<SceneBean> sceneBeans = scenePlusService.listCleanOss4TestCamera(cameraIds, cleanTestCameraMonth);
+        this.cleanOrig4Delete(sceneBeans, true, 3);
+    }
+
+    @Override
+    public void coldStorageHomeV3() {
+        //查询所有计算时间超过限定时间的场景,计算成功、未被删除
+        List<SceneBean> sceneBeans = sceneProService.listColdStorageScene(coldStorageMonth);
+        this.coldStorage(sceneBeans);
+    }
+
+    @Override
+    public void coldStorageHomeV4() {
+        //查询所有计算时间超过限定时间的场景,计算成功、未被删除
+        List<SceneBean> sceneBeans = scenePlusService.listColdStorageScene(coldStorageMonth);
+        this.coldStorage(sceneBeans);
+    }
+
+    private void coldStorage(List<SceneBean> sceneBeans){
+        if(CollUtil.isEmpty(sceneBeans)){
+            return;
+        }
+        sceneBeans.parallelStream().forEach(scene->{
+            boolean lock = this.lock(scene.getDataSource());
+            try {
+                if(lock) {
+                    this.coldStorageHandler(scene);
+                    sceneColdStorageLogService.saveLog(scene.getNum(), scene.getDataSource(), 1, 1, null);
+                    sceneColdStorageService.save(scene.getNum(), 1, coldBucket, bucket);
+                }
+            }catch (Exception e){
+                log.error("冷归档失败,num:{}" + scene.getNum(), e);
+                sceneColdStorageLogService.saveLog(scene.getNum(), scene.getDataSource(),1, CommonSuccessStatus.FAIL.code(), ExceptionUtil.stacktraceToString(e, 3000));
+            }finally {
+                this.releaseLock(scene.getDataSource());
+            }
+        });
+    }
+
+    private void coldStorageHandler(SceneBean scene){
+        String dataSource = scene.getDataSource();
+        if(StrUtil.isEmpty(dataSource) || dataSource.length() < 10) {
+            return;
+        }
+        String homePath = dataSource.replace(ConstantFilePath.BUILD_MODEL_PATH, ConstantFilePath.OSS_PREFIX);
+
+        //将文件复制到冷归档bucket
+        if(fYunFileConfig.getFyunType().equals(FYunTypeEnum.AWS.code())){
+            fYunFileService.copyFileToArchive(bucket, homePath, coldBucket, homePath);
+        }else{
+            fYunFileService.copyFileBetweenBucket(bucket, homePath, coldBucket, homePath);
+        }
+
+        List<String> origList = fYunFileService.listRemoteFiles(bucket, homePath);
+        List<String> coldList = fYunFileService.listRemoteFiles(coldBucket, homePath);
+        if(origList.size() != coldList.size()){
+            throw new RuntimeException("复制文件到冷归档bucket失败");
+        }
+
+        //删除标准bucket文件
+        fYunFileService.deleteFolder(homePath);
+    }
+}

+ 33 - 0
src/main/java/com/fdkankan/scene/service/impl/SceneColdStorageLogServiceImpl.java

@@ -0,0 +1,33 @@
+package com.fdkankan.scene.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.scene.entity.SceneColdStorageLog;
+import com.fdkankan.scene.mapper.ISceneColdStorageLogMapper;
+import com.fdkankan.scene.service.ISceneColdStorageLogService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 场景冷归档日志表 服务实现类
+ * </p>
+ *
+ * @author 
+ * @since 2023-07-12
+ */
+@Service
+public class SceneColdStorageLogServiceImpl extends ServiceImpl<ISceneColdStorageLogMapper, SceneColdStorageLog> implements ISceneColdStorageLogService {
+
+    public void saveLog(String num, String path, Integer type, Integer state, String reason){
+        //清除旧的日志
+        this.remove(new LambdaQueryWrapper<SceneColdStorageLog>().eq(SceneColdStorageLog::getNum, num));
+        SceneColdStorageLog sceneColdStorageLog = new SceneColdStorageLog();
+        sceneColdStorageLog.setNum(num);
+        sceneColdStorageLog.setPath(path);
+        sceneColdStorageLog.setType(type);
+        sceneColdStorageLog.setState(state);
+        sceneColdStorageLog.setReason(reason);
+        this.saveOrUpdate(sceneColdStorageLog);
+    }
+
+}

+ 36 - 0
src/main/java/com/fdkankan/scene/service/impl/SceneColdStorageServiceImpl.java

@@ -0,0 +1,36 @@
+package com.fdkankan.scene.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.fdkankan.scene.entity.SceneColdStorage;
+import com.fdkankan.scene.mapper.ISceneColdStorageMapper;
+import com.fdkankan.scene.service.ISceneColdStorageService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.Objects;
+
+/**
+ * <p>
+ * 场景封存状态表 服务实现类
+ * </p>
+ *
+ * @author 
+ * @since 2023-07-25
+ */
+@Service
+public class SceneColdStorageServiceImpl extends ServiceImpl<ISceneColdStorageMapper, SceneColdStorage> implements ISceneColdStorageService {
+
+    @Override
+    public void save(String num, Integer state, String coldBucket, String standarBucket) {
+
+        SceneColdStorage sceneColdStorage = this.getOne(new LambdaQueryWrapper<SceneColdStorage>().eq(SceneColdStorage::getNum, num));
+        if(Objects.isNull(sceneColdStorage)){
+            sceneColdStorage = new SceneColdStorage();
+        }
+        sceneColdStorage.setNum(num);
+        sceneColdStorage.setState(state);
+        sceneColdStorage.setColdBucket(coldBucket);
+        sceneColdStorage.setBucket(standarBucket);
+        this.saveOrUpdate(sceneColdStorage);
+    }
+}

+ 380 - 4
src/main/java/com/fdkankan/scene/service/impl/SceneEditInfoExtServiceImpl.java

@@ -1,20 +1,42 @@
 package com.fdkankan.scene.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.common.constant.CommonStatus;
 import com.fdkankan.common.constant.ErrorCode;
+import com.fdkankan.common.constant.FileBizType;
 import com.fdkankan.common.exception.BusinessException;
+import com.fdkankan.common.util.FileUtils;
+import com.fdkankan.fyun.face.FYunFileServiceInterface;
+import com.fdkankan.model.constants.ConstantFilePath;
+import com.fdkankan.model.constants.UploadFilePath;
+import com.fdkankan.redis.constant.RedisKey;
+import com.fdkankan.redis.constant.RedisLockKey;
+import com.fdkankan.redis.util.RedisLockUtil;
+import com.fdkankan.redis.util.RedisUtil;
+import com.fdkankan.scene.bean.TagBean;
 import com.fdkankan.scene.entity.SceneEditInfo;
 import com.fdkankan.scene.entity.SceneEditInfoExt;
 import com.fdkankan.scene.entity.ScenePlus;
+import com.fdkankan.scene.entity.ScenePlusExt;
 import com.fdkankan.scene.mapper.ISceneEditInfoExtMapper;
-import com.fdkankan.scene.service.ISceneEditInfoExtService;
-import com.fdkankan.scene.service.ISceneEditInfoService;
-import com.fdkankan.scene.service.IScenePlusService;
-import java.util.Objects;
+import com.fdkankan.scene.service.*;
+import com.fdkankan.scene.vo.*;
+import com.fdkankan.web.response.ResultData;
+import org.aspectj.apache.bcel.generic.RET;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
 /**
  * <p>
  *  服务实现类
@@ -29,7 +51,17 @@ public class SceneEditInfoExtServiceImpl extends ServiceImpl<ISceneEditInfoExtMa
     @Autowired
     private IScenePlusService scenePlusService;
     @Autowired
+    private IScenePlusExtService scenePlusExtService;
+    @Autowired
     private ISceneEditInfoService sceneEditInfoService;
+    @Autowired
+    private RedisUtil redisUtil;
+    @Autowired
+    private RedisLockUtil redisLockUtil;
+    @Autowired
+    private FYunFileServiceInterface fYunFileService;
+    @Autowired
+    private ISceneUploadService sceneUploadService;
 
     @Override
     public SceneEditInfoExt getByScenePlusId(long scenePlusId) {
@@ -53,4 +85,348 @@ public class SceneEditInfoExtServiceImpl extends ServiceImpl<ISceneEditInfoExtMa
         sceneEditInfoExt.setTours(tours);
         this.updateById(sceneEditInfoExt);
     }
+
+    @Override
+    public ResultData saveBillboards(BaseJsonArrayParamVO param) throws Exception {
+        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
+
+        this.addOrUpdateBillboards(param.getNum(), param.getData());
+
+        this.addOrUpdateBillboardsStyles(param.getNum(), param.getStyles());
+
+        //保存数据库
+        SceneEditInfoExt sceneEditInfoExt = this.getByScenePlusId(scenePlus.getId());
+        this.updateBillboards(param.getNum(), sceneEditInfoExt);
+//        this.updateById(sceneEditInfoExt);
+
+        sceneEditInfoService.upgradeVersionById(sceneEditInfoExt.getEditInfoId());
+
+        return ResultData.ok();
+    }
+
+    private void addOrUpdateBillboardsStyles(String num, List<JSONObject> styles) throws Exception{
+
+        this.syncBillboardsStylesFromFileToRedis(num);
+
+        if(CollUtil.isEmpty(styles)){
+            return;
+        }
+
+        long time = Calendar.getInstance().getTimeInMillis();
+        Map<String, String> styleMap = new HashMap<>();
+        AtomicInteger index = new AtomicInteger();
+        styles.stream().forEach(style->{
+            String id = style.getString("sid");
+            style.put("createTime", time + index.getAndIncrement());
+            styleMap.put(id, style.toJSONString());
+        });
+
+        String key = String.format(RedisKey.SCENE_BILLBOARDS_STYLES, num);
+        redisUtil.hmset(key, styleMap);
+
+        //写入本地文件,作为备份
+        this.writeBillboardStylesJson(num);
+    }
+
+    private void syncBillboardsStylesFromFileToRedis(String num) throws Exception{
+
+        String key = String.format(RedisKey.SCENE_BILLBOARDS_STYLES, num);
+        boolean exist = redisUtil.hasKey(key);
+        if(exist){
+            return;
+        }
+        String lockKey = String.format(RedisLockKey.LOCK_BILLBOARDS_STYLES_SYNC, num);
+        String lockVal = cn.hutool.core.lang.UUID.randomUUID().toString();
+        boolean lock = redisLockUtil.lock(lockKey, lockVal, RedisKey.EXPIRE_TIME_1_MINUTE);
+        if(!lock){
+            throw new BusinessException(ErrorCode.SYSTEM_BUSY);
+        }
+        try{
+            exist = redisUtil.hasKey(key);
+            if(exist){
+                return;
+            }
+            String stylesPath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num);
+            String stylesData = FileUtils.readUtf8String(stylesPath + "billboards-styles.json");
+            if(StrUtil.isEmpty(stylesData)){
+                return;
+            }
+            JSONArray stylesArr = JSON.parseArray(stylesData);
+            if(CollUtil.isEmpty(stylesArr)){
+                return;
+            }
+            Map<String, String> styleMap = new HashMap<>();
+            for (Object style : stylesArr) {
+                JSONObject styleObj = (JSONObject)style;
+                String id = styleObj.getString("sid");
+                styleMap.put(id, styleObj.toJSONString());
+            }
+            redisUtil.hmset(key, styleMap);
+        }finally {
+            redisLockUtil.unlockLua(lockKey, lockVal);
+        }
+
+    }
+
+    @Override
+    public ResultData deleteBillboards(DeleteSidListParamVO param) throws Exception {
+        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
+        ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
+        String bucket = scenePlusExt.getYunFileBucket();
+
+        List<String> deleteSidList = param.getSidList();
+
+        this.syncBillboardsFromFileToRedis(param.getNum());
+
+        //处理删除状态数据
+        this.deleteBillboards(param.getNum(), deleteSidList, bucket);
+
+        //写入本地文件,作为备份
+        this.writeBillboardJson(param.getNum());
+
+        //保存数据库
+        SceneEditInfoExt sceneEditInfoExt = this.getByScenePlusId(scenePlus.getId());
+        this.updateBillboards(param.getNum(), sceneEditInfoExt);
+        sceneEditInfoService.upgradeVersionById(sceneEditInfoExt.getEditInfoId());
+
+        return ResultData.ok();
+    }
+
+    @Override
+    public JSONObject listBillboards(BaseSceneParamVO param) throws Exception {
+
+        JSONObject result = new JSONObject();
+        List<JSONObject> tags = new ArrayList<>();
+        List<JSONObject> styles = new ArrayList<>();
+        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
+        SceneEditInfoExt sceneEditInfoExt = this.getByScenePlusId(scenePlus.getId());
+
+        this.syncBillboardsFromFileToRedis(param.getNum());
+
+        //获取指示牌数据
+        String key = String.format(RedisKey.SCENE_BILLBOARDS, param.getNum());
+        List<String> list = redisUtil.hgetValues(key);
+        if(CollUtil.isNotEmpty(list)){
+            List<TagBean> sortList = list.stream().map(str -> {
+                JSONObject jsonObject = JSON.parseObject(str);
+                TagBean tagBean = new TagBean();
+                tagBean.setCreateTime(jsonObject.getLong("createTime"));
+                jsonObject.remove("createTime");
+                tagBean.setTag(jsonObject);
+                return tagBean;
+            }).collect(Collectors.toList());
+            sortList.sort(Comparator.comparingLong(TagBean::getCreateTime).reversed());
+            tags = sortList.stream().map(item -> item.getTag()).collect(Collectors.toList());
+        }
+        result.put("tags", tags);
+
+        //获取图标数据
+        this.syncBillboardsStylesFromFileToRedis(param.getNum());
+        key = String.format(RedisKey.SCENE_BILLBOARDS_STYLES, param.getNum());
+        List<String> sytlelist = redisUtil.hgetValues(key);
+        if(CollUtil.isNotEmpty(sytlelist)){
+            List<TagBean> stileSortList = sytlelist.stream().map(str -> {
+                JSONObject jsonObject = JSON.parseObject(str);
+                TagBean tagBean = new TagBean();
+                tagBean.setCreateTime(jsonObject.getLong("createTime"));
+                jsonObject.remove("createTime");
+                tagBean.setTag(jsonObject);
+                return tagBean;
+            }).collect(Collectors.toList());
+            stileSortList.sort(Comparator.comparingLong(TagBean::getCreateTime).reversed());
+            styles = stileSortList.stream().map(item -> item.getTag()).collect(Collectors.toList());
+        }
+        result.put("styles", styles);
+
+        return result;
+    }
+
+    private void deleteBillboards(String num, List<String> deleteSidList, String bucket) throws Exception {
+        if(CollUtil.isEmpty(deleteSidList)){
+            return;
+        }
+
+        //从redis中加载热点数据
+        String key = String.format(RedisKey.SCENE_BILLBOARDS, num);
+        List<String> deletDataList = redisUtil.hMultiGet(key, deleteSidList);
+        if(CollUtil.isEmpty(deletDataList))
+            return;
+        //从redis中移除热点数据
+        redisUtil.hdel(key, deleteSidList.toArray());
+    }
+
+    private void addOrUpdateBillboards(String num, List<JSONObject> data) throws Exception{
+        Map<String, String> addOrUpdateMap = new HashMap<>();
+        int i = 0;
+        for (JSONObject jsonObject : data) {
+            jsonObject.put("createTime", Calendar.getInstance().getTimeInMillis() + i++);
+            addOrUpdateMap.put(jsonObject.getString("sid"), JSON.toJSONString(jsonObject));
+        }
+
+        this.syncBillboardsFromFileToRedis(num);
+
+        //处理新增和修改数据
+        this.addOrUpdateBillboardsHandler(num, addOrUpdateMap);
+    }
+
+    /**
+     * <p>
+     保证指示牌数据安全性,当redis宕机导致热点数据丢失时,可以从文件中读取,恢复到redis
+     * </p>
+     * @author dengsixing
+     * @date 2022/3/3
+     **/
+    private void syncBillboardsFromFileToRedis(String num) throws Exception{
+
+        String key = String.format(RedisKey.SCENE_BILLBOARDS, num);
+        boolean exist = redisUtil.hasKey(key);
+        if(exist){
+            return;
+        }
+        String lockKey = String.format(RedisLockKey.LOCK_BILLBOARDS_SYNC, num);
+        String lockVal = cn.hutool.core.lang.UUID.randomUUID().toString();
+        boolean lock = redisLockUtil.lock(lockKey, lockVal, RedisKey.EXPIRE_TIME_1_MINUTE);
+        if(!lock){
+            throw new BusinessException(ErrorCode.SYSTEM_BUSY);
+        }
+        try{
+            exist = redisUtil.hasKey(key);
+            if(exist){
+                return;
+            }
+            String billboardsFilePath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + "billboards.json";
+            String billboardsData = FileUtils.readUtf8String(billboardsFilePath);
+            if(StrUtil.isEmpty(billboardsData)){
+                return;
+            }
+            JSONArray tagsArr = JSON.parseArray(billboardsData);
+            if(CollUtil.isEmpty(tagsArr)){
+                return;
+            }
+            Map<String, String> map = new HashMap<>();
+            for (Object o : tagsArr) {
+                JSONObject jo = (JSONObject)o;
+                map.put(jo.getString("sid"), jo.toJSONString());
+            }
+            redisUtil.hmset(key, map);
+        }finally {
+            redisLockUtil.unlockLua(lockKey, lockVal);
+        }
+    }
+
+    private void addOrUpdateBillboardsHandler(String num, Map<String, String> addOrUpdateMap){
+        if(CollUtil.isEmpty(addOrUpdateMap))
+            return;
+
+        //批量写入缓存
+        String key = String.format(RedisKey.SCENE_BILLBOARDS, num);
+        redisUtil.hmset(key, addOrUpdateMap);
+
+        //写入本地文件,作为备份
+        this.writeBillboardJson(num);
+    }
+
+    /**
+     * <p>
+     热点数据保存
+
+     * </p>
+     * @author dengsixing
+     * @date 2022/3/3
+     *
+     **/
+    private void writeBillboardJson(String num){
+        String lockKey = String.format(RedisLockKey.LOCK_BILLBOARDS_SYNC, num);
+        String lockVal = cn.hutool.core.lang.UUID.randomUUID().toString();
+        boolean lock = redisLockUtil.lock(lockKey, lockVal, RedisKey.EXPIRE_TIME_1_MINUTE);
+        if(!lock){
+            return;
+        }
+        try{
+            String dataKey = String.format(RedisKey.SCENE_BILLBOARDS, num);
+            String hotJsonPath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + "billboards.json";
+            if(!redisUtil.hasKey(dataKey)){
+                FileUtil.del(hotJsonPath);
+                return;
+            }
+            Map<String, String> billboardMap = redisUtil.hmget(dataKey);
+            List<JSONObject>  billboardList = billboardMap.entrySet().stream().map(entry->JSON.parseObject(entry.getValue())).collect(Collectors.toList());
+            FileUtil.writeUtf8String(JSON.toJSONString(billboardList), hotJsonPath);
+        }finally {
+            redisLockUtil.unlockLua(lockKey, lockVal);
+        }
+    }
+
+    private void writeBillboardStylesJson(String num){
+        String lockKey = String.format(RedisLockKey.LOCK_BILLBOARDS_STYLES_SYNC, num);
+        String lockVal = cn.hutool.core.lang.UUID.randomUUID().toString();
+        boolean lock = redisLockUtil.lock(lockKey, lockVal, RedisKey.EXPIRE_TIME_1_MINUTE);
+        if(!lock){
+            return;
+        }
+        try{
+            String dataKey = String.format(RedisKey.SCENE_BILLBOARDS_STYLES, num);
+            String stylesPath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + "billboards-styles.json";
+            if(!redisUtil.hasKey(dataKey)){
+                FileUtil.del(stylesPath);
+                return;
+            }
+            Map<String, String> billboardStylesMap = redisUtil.hmget(dataKey);
+            List<JSONObject>  billboardStyleList = billboardStylesMap.entrySet().stream().map(entry->JSON.parseObject(entry.getValue())).collect(Collectors.toList());
+            FileUtil.writeUtf8String(JSON.toJSONString(billboardStyleList), stylesPath);
+        }finally {
+            redisLockUtil.unlockLua(lockKey, lockVal);
+        }
+    }
+
+    private void updateBillboards(String num, SceneEditInfoExt sceneEditInfoExt){
+        //查询缓存是否包含热点数据
+        String key = String.format(RedisKey.SCENE_BILLBOARDS, num);
+        Map<String, String> billboardsMap = redisUtil.hmget(key);
+        boolean hashBillboards= false;
+        for (Map.Entry<String, String> tagMap : billboardsMap.entrySet()) {
+            if(StrUtil.isEmpty(tagMap.getValue())){
+                continue;
+            }
+            hashBillboards = true;
+            break;
+        }
+
+        //更改热点状态
+        sceneEditInfoExt.setBillboards(hashBillboards ? CommonStatus.YES.code().intValue() : CommonStatus.NO.code().intValue());
+        this.updateById(sceneEditInfoExt);
+    }
+
+    @Override
+    public ResultData deleteBillboardsStyles(DeleteStylesParamVO param) throws Exception {
+        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
+        if (scenePlus == null)
+            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
+
+        List<String> sidList = param.getSidList();
+
+        this.syncBillboardsStylesFromFileToRedis(param.getNum());
+
+        String key = String.format(RedisKey.SCENE_BILLBOARDS_STYLES, param.getNum());
+        List<String> deleteList = redisUtil.hMultiGet(key, sidList);
+        redisUtil.hdel(key, sidList.toArray());
+
+        //写入本地文件,作为备份
+        this.writeBillboardStylesJson(param.getNum());
+
+        //删除oss文件
+        List<String> deleteFileList = deleteList.stream().map(str -> {
+            JSONObject parse = JSON.parseObject(str);
+            return parse.getString("url");
+        }).collect(Collectors.toList());
+        sceneUploadService.delete(
+                DeleteFileParamVO.builder()
+                        .num(param.getNum())
+                        .fileNames(deleteFileList)
+                        .bizType(FileBizType.BILLBOARD_ICON.code()).build());
+
+        return ResultData.ok();
+    }
+
+
 }

+ 63 - 42
src/main/java/com/fdkankan/scene/service/impl/SceneEditInfoServiceImpl.java

@@ -1,12 +1,8 @@
 package com.fdkankan.scene.service.impl;
-import cn.hutool.core.net.multipart.UploadFile;
 import cn.hutool.core.util.CharsetUtil;
 import com.fdkankan.common.constant.*;
 import com.fdkankan.common.util.FileSizeUtil;
-import com.fdkankan.common.util.MD5;
 import com.fdkankan.scene.vo.SaveFiltersParamVO;
-import io.opencensus.metrics.LongGauge;
-import java.util.Date;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
@@ -23,7 +19,6 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fdkankan.common.exception.BusinessException;
 import com.fdkankan.common.util.FileMd5Util;
 import com.fdkankan.common.util.FileUtils;
-import com.fdkankan.fyun.constant.FYunTypeEnum;
 import com.fdkankan.fyun.face.FYunFileServiceInterface;
 import com.fdkankan.model.constants.ConstantFilePath;
 import com.fdkankan.model.constants.UploadFilePath;
@@ -71,7 +66,7 @@ import com.fdkankan.scene.vo.BaseFileParamVO;
 import com.fdkankan.scene.vo.BaseSceneParamVO;
 import com.fdkankan.scene.vo.DeleteFileParamVO;
 import com.fdkankan.scene.vo.DeleteLinkPanParamVO;
-import com.fdkankan.scene.vo.DeleteLinkSceneStylesParamVO;
+import com.fdkankan.scene.vo.DeleteStylesParamVO;
 import com.fdkankan.scene.vo.DeleteMosaicParamVO;
 import com.fdkankan.scene.vo.DeleteSidParamVO;
 import com.fdkankan.scene.vo.DownloadVO;
@@ -195,6 +190,11 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
             sceneEditInfo.setVersion(sceneEditInfoDb.getVersion() + 1);
             this.updateById(sceneEditInfo);
         }
+        SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByEditInfoId(sceneEditInfo.getId());
+        if(Objects.nonNull(param.getSns())){
+            sceneEditInfoExt.setSnsInfo(JSON.toJSONString(param.getSns()));
+        }
+        sceneEditInfoExtService.updateById(sceneEditInfoExt);
 
         if(Objects.nonNull(param.getControls())){
             SceneEditControls sceneEditControls = BeanUtil.copyProperties(param.getControls(), SceneEditControls.class);
@@ -286,8 +286,11 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         //发布马赛克列表
         sceneJson.setMosaicList(this.getMosaicList(num));
 
+        //发布分享配置
+        sceneJson.setSns(JSON.parseObject(sceneEditInfoExt.getSnsInfo()));
+
         //处理热点数据,生成hot.json
-        this.publicHotData(num, sceneEditInfo, bucket);
+        this.publicHotData(num, bucket);
 
         //发布场景关联相关数据
         this.publicLinkSceneData(num, bucket);
@@ -298,6 +301,9 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         //发布摄像头数据
         this.publicSurveillance(num, sceneEditInfoExt.getSurveillances(), bucket);
 
+        //发布指示牌数据
+        this.publicBillboardData(num, bucket);
+
         //本地写sceneJson文件
         String localSceneJsonPath = String.format(ConstantFilePath.SCENE_DATA_PATH_V4, num) + "scene.json";
         FileUtils.writeFile(localSceneJsonPath, JSON.toJSONString(sceneJson));
@@ -305,10 +311,6 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         String sceneJsonPath = String.format(UploadFilePath.DATA_VIEW_PATH+"scene.json", num);
         fYunFileService.uploadFile(bucket, JSON.toJSONBytes(sceneJson), sceneJsonPath);
 
-        //sceneJson放入缓存
-        String key = String.format(RedisKey.SCENE_JSON, num);
-        redisUtil.set(key, JSON.toJSONString(sceneJson));
-
         //删除发布数据中的user目录
         String publicUserPath = String.format(UploadFilePath.USER_VIEW_PATH, num);
         List<String> userViewFileList = fYunFileService.listRemoteFiles(bucket, publicUserPath);
@@ -321,6 +323,10 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         String viewPath = String.format(UploadFilePath.USER_VIEW_PATH, param.getNum());
         fYunFileService.copyFileBetweenBucket(bucket, editPath, bucket, viewPath);
 
+        //sceneJson放入缓存
+        String key = String.format(RedisKey.SCENE_JSON, num);
+        redisUtil.set(key, JSON.toJSONString(sceneJson));
+
         //入库
         if(sceneEditInfo.getId() == null){
             this.save(sceneEditInfo);
@@ -398,7 +404,7 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
 
     }
 
-    private void publicHotData(String sceneNum, SceneEditInfo sceneEditInfo, String bucket) throws IOException {
+    private void publicHotData(String sceneNum, String bucket) throws IOException {
         String hotDataKey = String.format(RedisKey.SCENE_HOT_DATA, sceneNum);
         Map<String, String> hotMap = redisUtil.hmget(hotDataKey);
 
@@ -425,6 +431,18 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
 
     }
 
+    private void publicBillboardData(String sceneNum, String bucket) throws IOException {
+        String Key = String.format(RedisKey.SCENE_BILLBOARDS, sceneNum);
+        String userEditPath = String.format(UploadFilePath.USER_EDIT_PATH, sceneNum) + "billboards.json";
+        List<String> list = redisUtil.hgetValues(Key);
+        if(CollUtil.isEmpty(list)){
+            fYunFileService.deleteFile(bucket, userEditPath);
+            return;
+        }
+        List<JSONObject> collect = list.stream().map(str -> JSON.parseObject(str)).collect(Collectors.toList());
+        fYunFileService.uploadFile(bucket, JSON.toJSONString(collect).getBytes(), userEditPath);
+    }
+
     @Override
     public SceneInfoVO getSceneInfo(@Var SceneInfoParamVO param) throws Exception{
         SceneInfoReqType sceneInfoReqType = SceneInfoReqType.get(param.getReqType());
@@ -474,7 +492,7 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         }
         sceneInfoVO.setControls(BeanUtil.copyProperties(sceneEditControls, SceneEditControlsVO.class));
         sceneInfoVO.setNum(num);
-        sceneInfoVO.setCreateTime(scenePlus.getCreateTime());
+        sceneInfoVO.setCreateTime(scenePlusExt.getAlgorithmTime());
 
         sceneInfoVO.setSceneResolution(scenePlusExt.getSceneResolution());
         sceneInfoVO.setSceneFrom(scenePlusExt.getSceneFrom());
@@ -485,6 +503,7 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
             sceneInfoVO.setMosaicList(this.getMosaicList(num));
         }
         sceneInfoVO.setSpace(FileSizeUtil.convert(scenePlusExt.getSpace(), FileSizeUnitType.MB.code()));
+        sceneInfoVO.setSns(JSON.parseObject(sceneEditInfoExt.getSnsInfo()));
 
         this.SortBoxVideos(sceneInfoVO);
 
@@ -493,6 +512,12 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         return sceneInfoVO;
     }
 
+    public static void main(String[] args) {
+        String test = "";
+        JSONObject jsonObject = JSON.parseObject(test);
+        System.out.println(jsonObject);
+    }
+
     private void SortBoxVideos(SceneInfoVO sceneInfoVO){
         String boxVideos = sceneInfoVO.getBoxVideos();
         if(StrUtil.isEmpty(boxVideos)){
@@ -571,33 +596,29 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         String sceneJson = redisUtil.get(key);
         SceneInfoVO sceneInfoVO = null;
         //先查询redis
-        if(StrUtil.isNotEmpty(sceneJson)) {
-            sceneInfoVO = JSON.parseObject(sceneJson, SceneInfoVO.class);
-            sceneInfoVO.setScenePassword(null);
-            if(Objects.isNull(sceneInfoVO.getFloorPlanAngle())){
-                sceneInfoVO.setFloorPlanAngle(0f);
-            }
-            if(Objects.isNull(sceneInfoVO.getFloorPlanCompass())){
-                sceneInfoVO.setFloorPlanCompass(0f);
-            }
-            return sceneInfoVO;
+        if(StrUtil.isEmpty(sceneJson)) {
+            String objectName = String.format(ConstantFilePath.SCENE_VIEW_DATA_DATA_SCENEJSON, num);
+            sceneJson = fYunFileService.getFileContent(scenePlusExt.getYunFileBucket(), objectName);
+            redisUtil.set(key, sceneJson);
         }
-
-        //如果redis没找到,从scene.json中获取
-        String objectName = String.format(ConstantFilePath.SCENE_VIEW_DATA_DATA_SCENEJSON, num);
-        String objectContent = fYunFileService.getFileContent(scenePlusExt.getYunFileBucket(), objectName);
-        log.info("获取scene.json内容,path:{}, content:{}", objectName, objectContent);
-        if(StrUtil.isEmpty(objectContent))
-            return null;
-        sceneInfoVO = JSON.parseObject(objectContent, SceneInfoVO.class);
+        sceneInfoVO = JSON.parseObject(sceneJson, SceneInfoVO.class);
+        sceneInfoVO.setScenePassword(null);
         if(Objects.isNull(sceneInfoVO.getFloorPlanAngle())){
             sceneInfoVO.setFloorPlanAngle(0f);
         }
         if(Objects.isNull(sceneInfoVO.getFloorPlanCompass())){
             sceneInfoVO.setFloorPlanCompass(0f);
         }
-        redisUtil.set(key, JSON.toJSONString(sceneInfoVO));
-        sceneInfoVO.setScenePassword(null);
+        SceneEditControlsVO controls = sceneInfoVO.getControls();
+        if(Objects.isNull(controls.getShowShare())){
+            controls.setShowShare(CommonStatus.YES.code().intValue());
+        }
+        if(Objects.isNull(controls.getShowCapture())){
+            controls.setShowCapture(CommonStatus.YES.code().intValue());
+        }
+        if(Objects.isNull(controls.getShowBillboardTitle())){
+            controls.setShowBillboardTitle(CommonStatus.YES.code().intValue());
+        }
 
         return sceneInfoVO;
     }
@@ -686,10 +707,10 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         String bucket = scenePlusExt.getYunFileBucket();
         String path = scenePlusExt.getDataSource();
 
-        //户型图上传
-        String ossResultPath = String.format(UploadFilePath.scene_result_data_path, num);
-        String floorplanCadPath = ossResultPath + "floorplan_cad/";
-        fYunFileService.copyFileBetweenBucket(bucket, floorplanCadPath, bucket, String.format(UploadFilePath.USER_EDIT_PATH, num));
+        //户型图上传 恢复默认并发布同时点击刷新查看页面,平面图会变形,所以这里先注释掉 bug-36281 2023-05-04
+//        String ossResultPath = String.format(UploadFilePath.scene_result_data_path, num);
+//        String floorplanCadPath = ossResultPath + "floorplan_cad/";
+//        fYunFileService.copyFileBetweenBucket(bucket, floorplanCadPath, bucket, String.format(UploadFilePath.USER_EDIT_PATH, num));
 
 //        String  userEditPath = UploadFilePath.USER_EDIT_PATH + "floor-cad-%s.%s";
 //        String floorCadPath = path + "/results/floorplan_cad";
@@ -855,16 +876,16 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
         String bucket = scenePlusExt.getYunFileBucket();
 
-        String key = String.format(UploadFilePath.DATA_VIEW_PATH, param.getNum()) + "floorplan_cad.json";
-        String floorplanCadJson = fYunFileService.getFileContent(bucket, key);
-        if(StrUtil.isEmpty(floorplanCadJson)){
+        String key = String.format(UploadFilePath.USER_EDIT_PATH, param.getNum()) + "floorplan.json";
+        String floorplanJson = fYunFileService.getFileContent(bucket, key);
+        if(StrUtil.isEmpty(floorplanJson)){
             return ResultData.ok();
         }
         Map<Integer, String> renameMap = new HashMap<>();
         param.getFloors().stream().forEach(floor->{
             renameMap.put(floor.getSubgroup(), floor.getName());
         });
-        JSONObject jsonObject = JSON.parseObject(floorplanCadJson);
+        JSONObject jsonObject = JSON.parseObject(floorplanJson);
         if(Objects.isNull(jsonObject)){
             return ResultData.ok();
         }
@@ -2079,7 +2100,7 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
     }
 
     @Override
-    public ResultData deleteStyles(DeleteLinkSceneStylesParamVO param) throws Exception {
+    public ResultData deleteStyles(DeleteStylesParamVO param) throws Exception {
         ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
         if (scenePlus == null)
             throw new BusinessException(ErrorCode.FAILURE_CODE_5005);

+ 3 - 3
src/main/java/com/fdkankan/scene/service/impl/SceneEditServiceImpl.java

@@ -122,9 +122,9 @@ public class SceneEditServiceImpl implements ISceneEditService {
         sceneAuthVO.setExclude(new ArrayList<>());
         sceneAuthVO.setInclude(new ArrayList<>());
 
-        //判断本地资源是否已本删除,如果已删除,前端根据字段值为true提示用户不能使用某些功能,需要重算
-        Date algorithmTime = scenePlusExt.getAlgorithmTime() == null ? scenePlus.getCreateTime() : scenePlusExt.getAlgorithmTime();
-        if (!ObjectUtils.isEmpty(expiredMonth) && com.fdkankan.common.util.DateUtil.delay(algorithmTime, expiredMonth, Calendar.MONTH).before(new Date())) {
+        //判断data.json是否存在,如果存在,则证明计算在未被定时任务删除前上传过oss
+        boolean exist = fYunFileService.fileExist(String.format(UploadFilePath.scene_result_data_path, num).concat("data.json"));
+        if(!exist){
             sceneAuthVO.setSourceExpired(true);
         }
 

+ 36 - 5
src/main/java/com/fdkankan/scene/service/impl/ScenePlusServiceImpl.java

@@ -1,6 +1,8 @@
 package com.fdkankan.scene.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.date.DateField;
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.qrcode.QrCodeUtil;
@@ -15,6 +17,7 @@ import com.fdkankan.common.exception.BusinessException;
 import com.fdkankan.fyun.face.FYunFileServiceInterface;
 import com.fdkankan.model.constants.ConstantFilePath;
 import com.fdkankan.model.constants.UploadFilePath;
+import com.fdkankan.scene.bean.SceneBean;
 import com.fdkankan.scene.entity.SceneEditInfoExt;
 import com.fdkankan.scene.entity.ScenePro;
 import com.fdkankan.scene.service.ISceneEditInfoExtService;
@@ -37,9 +40,8 @@ import com.fdkankan.scene.vo.BaseSceneParamVO;
 import com.fdkankan.scene.vo.SceneCheckKeyParamVO;
 import com.fdkankan.scene.vo.SceneDataDownloadVO;
 import java.io.File;
-import java.util.List;
-import java.util.Objects;
-import java.util.UUID;
+import java.util.*;
+
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -222,8 +224,8 @@ public class ScenePlusServiceImpl extends ServiceImpl<IScenePlusMapper, ScenePlu
         String outPathEn = ConstantFilePath.BASE_PATH + File.separator + "sceneQRcode/"+num+"_en.png";
 
         String webSize = mainUrl + "/" + sceneProNewUrl + num;
-        QrCodeUtil.generate(webSize, QrConfig.create().setImg(logoPath).setWidth(512).setHeight(512), FileUtil.file(outPathZh));
-        QrCodeUtil.generate(webSize + "&lang=en", QrConfig.create().setImg(logoPath).setWidth(512).setHeight(512), FileUtil.file(outPathEn));
+        QrCodeUtil.generate(webSize, QrConfig.create().setImg(logoPath).setWidth(1024).setHeight(1024), FileUtil.file(outPathZh));
+        QrCodeUtil.generate(webSize + "&lang=en", QrConfig.create().setImg(logoPath).setWidth(1024).setHeight(1024), FileUtil.file(outPathEn));
         //上传logo图片
         String ossLogoPath = String.format(UploadFilePath.DOWNLOADS_QRCODE, num) + "shareLogo" + extName;
         fYunFileService.uploadFile(scenePlusExt.getYunFileBucket(), logoPath, ossLogoPath);
@@ -242,4 +244,33 @@ public class ScenePlusServiceImpl extends ServiceImpl<IScenePlusMapper, ScenePlu
 
         return ResultData.ok();
     }
+
+    @Override
+    public List<SceneBean> listCleanOrigScene(int cleanOrigMonth) {
+        Date time = Calendar.getInstance().getTime();
+        time = DateUtil.beginOfDay(DateUtil.offset(time, DateField.MONTH, -cleanOrigMonth));
+        return this.baseMapper.selectCleanOrigScene(time);
+    }
+
+    @Override
+    public List<SceneBean> listCleanOss4DeletedScene(int month) {
+        Date time = Calendar.getInstance().getTime();
+        time = DateUtil.beginOfDay(DateUtil.offset(time, DateField.MONTH, -month));
+        return this.baseMapper.selectCleanOrigSceneDeleted(time);
+    }
+
+    @Override
+    public List<SceneBean> listCleanOss4TestCamera(Set<Long> cameraIds, int month) {
+        Date time = Calendar.getInstance().getTime();
+        time = DateUtil.beginOfDay(DateUtil.offset(time, DateField.MONTH, -month));
+        return this.baseMapper.listCleanOss4TestCamera(cameraIds, time);
+
+    }
+
+    @Override
+    public List<SceneBean> listColdStorageScene(int cleanOrigMonth) {
+        Date time = Calendar.getInstance().getTime();
+        time = DateUtil.beginOfDay(DateUtil.offset(time, DateField.MONTH, -cleanOrigMonth));
+        return this.baseMapper.selectColdStorageScene(time);
+    }
 }

+ 34 - 2
src/main/java/com/fdkankan/scene/service/impl/SceneProServiceImpl.java

@@ -1,6 +1,8 @@
 package com.fdkankan.scene.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateField;
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.util.RuntimeUtil;
 import cn.hutool.core.util.StrUtil;
@@ -16,6 +18,7 @@ import com.fdkankan.model.constants.ConstantFileName;
 import com.fdkankan.model.constants.ConstantFilePath;
 import com.fdkankan.model.constants.UploadFilePath;
 import com.fdkankan.common.exception.BusinessException;
+import com.fdkankan.scene.bean.SceneBean;
 import com.fdkankan.web.response.ResultData;
 import com.fdkankan.model.utils.ComputerUtil;
 import com.fdkankan.model.utils.ConvertUtils;
@@ -1068,8 +1071,10 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
 
     public static void main(String[] args) {
 
-        ZipUtil.zip("C:\\Users\\dsx\\Desktop\\新建文件夹\\temp\\mesh\\aaa\\mesh", "C:\\Users\\dsx\\Desktop\\新建文件夹\\temp\\mesh\\aaa\\mesh\\mesh.zip");
-        System.out.println(123);
+        Date time = Calendar.getInstance().getTime();
+        time = DateUtil.beginOfDay(DateUtil.offset(time, DateField.MONTH, -12));
+        System.out.println(time);
+
     }
 
 
@@ -1123,4 +1128,31 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
         return ResultData.ok(url);
     }
 
+    @Override
+    public List<SceneBean> listCleanOrigScene(int cleanOrigMonth) {
+        Date time = Calendar.getInstance().getTime();
+        time = DateUtil.beginOfDay(DateUtil.offset(time, DateField.MONTH, -cleanOrigMonth));
+        return this.baseMapper.selectCleanOrigScene(time);
+    }
+
+    @Override
+    public List<SceneBean> listCleanOss4DeletedScene(int month) {
+        Date time = Calendar.getInstance().getTime();
+        time = DateUtil.beginOfDay(DateUtil.offset(time, DateField.MONTH, -month));
+        return this.baseMapper.listCleanOss4DeletedScene(time);
+    }
+
+    @Override
+    public List<SceneBean> listCleanOss4TestCamera(Set<Long> cameraIds, int month) {
+        Date time = Calendar.getInstance().getTime();
+        time = DateUtil.beginOfDay(DateUtil.offset(time, DateField.MONTH, -month));
+        return this.baseMapper.listCleanOss4TestCamera(cameraIds, time);
+    }
+
+    @Override
+    public List<SceneBean> listColdStorageScene(int cleanOrigMonth) {
+        Date time = Calendar.getInstance().getTime();
+        time = DateUtil.beginOfDay(DateUtil.offset(time, DateField.MONTH, -cleanOrigMonth));
+        return this.baseMapper.selectColdStorageScene(time);
+    }
 }

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

@@ -75,7 +75,7 @@ public class SceneServiceImpl implements ISceneService {
         file.transferTo(tempFile);
 
         //判断是否需要旋转
-        if(Objects.nonNull(rotate)){
+        if(Objects.nonNull(rotate) && rotate != 0){
             Image rotateImg = ImgUtil.rotate(ImageIO.read(tempFile), rotate);
             File tempRotateFile = File.createTempFile(uuid + "-rotate", extName);
             ImgUtil.write(rotateImg, tempRotateFile);

+ 8 - 4
src/main/java/com/fdkankan/scene/service/impl/SceneUploadServiceImpl.java

@@ -3,6 +3,7 @@ package com.fdkankan.scene.service.impl;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.date.TimeInterval;
+import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -11,6 +12,7 @@ import com.fdkankan.common.constant.ErrorCode;
 import com.fdkankan.common.constant.RecStatus;
 import com.fdkankan.common.constant.ServerCode;
 import com.fdkankan.common.util.FileUtils;
+import com.fdkankan.model.constants.ConstantFilePath;
 import com.fdkankan.model.constants.UploadFilePath;
 import com.fdkankan.common.exception.BusinessException;
 import com.fdkankan.web.response.ResultData;
@@ -137,8 +139,10 @@ public class SceneUploadServiceImpl extends ServiceImpl<ISceneUploadMapper, Scen
             String fileName = file.getOriginalFilename();
             // 获取文件后缀
             String prefix = fileName.substring(fileName.lastIndexOf("."));
-            File newFile = File.createTempFile(UUID.randomUUID().toString() ,prefix);
-            file.transferTo(newFile);
+            String path = String.format(ConstantFilePath.SCENE_TMP_PATH_V4, num).concat(UUID.randomUUID().toString()).concat(prefix);
+//            File newFile = File.createTempFile(UUID.randomUUID().toString() ,prefix);
+            FileUtil.mkParentDirs(path);
+            file.transferTo(new File(path));
             String realFileName = fileName;
             if(files.size() ==1 && StringUtils.isNotBlank(sendFileName)){
                 realFileName = sendFileName ;
@@ -151,7 +155,7 @@ public class SceneUploadServiceImpl extends ServiceImpl<ISceneUploadMapper, Scen
             String ossPath = StrUtil.isNotBlank(uploadPath) ? uploadPath : (String.format(UploadFilePath.USER_EDIT_PATH ,num) + realFileName);
             try {
                 TimeInterval timer = DateUtil.timer();
-                fYunFileService.uploadFile(bucket, newFile.getPath(), ossPath);
+                fYunFileService.uploadFile(bucket, path, ossPath);
                 System.out.println(timer.intervalRestart());
             }catch (Exception e){
                 log.error(ossPath+"上传文件失败"+e);
@@ -160,7 +164,7 @@ public class SceneUploadServiceImpl extends ServiceImpl<ISceneUploadMapper, Scen
 
             urlList.add(realFileName);
 
-            FileUtils.delFile(newFile.getPath());
+            FileUtils.delFile(path);
             //添加记录
             this.saveData(num,ossPath,bizType,userId);
         }

+ 12 - 0
src/main/java/com/fdkankan/scene/service/impl/SurveillanceServiceImpl.java

@@ -7,11 +7,13 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fdkankan.common.constant.CommonStatus;
 import com.fdkankan.common.constant.ErrorCode;
 import com.fdkankan.common.exception.BusinessException;
+import com.fdkankan.scene.entity.SceneEditInfo;
 import com.fdkankan.scene.entity.SceneEditInfoExt;
 import com.fdkankan.scene.entity.ScenePlus;
 import com.fdkankan.scene.entity.Surveillance;
 import com.fdkankan.scene.mapper.ISurveillanceMapper;
 import com.fdkankan.scene.service.ISceneEditInfoExtService;
+import com.fdkankan.scene.service.ISceneEditInfoService;
 import com.fdkankan.scene.service.IScenePlusService;
 import com.fdkankan.scene.service.ISurveillanceService;
 import com.fdkankan.scene.vo.BaseSidParamVO;
@@ -39,6 +41,8 @@ public class SurveillanceServiceImpl extends ServiceImpl<ISurveillanceMapper, Su
     private IScenePlusService scenePlusService;
     @Autowired
     private ISceneEditInfoExtService sceneEditInfoExtService;
+    @Autowired
+    private ISceneEditInfoService sceneEditInfoService;
 
     @Override
     public ResultData saveSurveillance(SurveillanceParamVO param) {
@@ -47,6 +51,7 @@ public class SurveillanceServiceImpl extends ServiceImpl<ISurveillanceMapper, Su
         if(Objects.isNull(scenePlus)){
             throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
         }
+        SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
         SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByScenePlusId(scenePlus.getId());
 
         Surveillance surveillance = this.getBySid(param.getNum(), param.getSid());
@@ -64,6 +69,9 @@ public class SurveillanceServiceImpl extends ServiceImpl<ISurveillanceMapper, Su
         sceneEditInfoExt.setSurveillances(CommonStatus.YES.code().intValue());
         sceneEditInfoExtService.updateById(sceneEditInfoExt);
 
+        sceneEditInfoService.upgradeVersionById(sceneEditInfo.getId());
+
+
         return ResultData.ok();
     }
 
@@ -73,6 +81,7 @@ public class SurveillanceServiceImpl extends ServiceImpl<ISurveillanceMapper, Su
         if(Objects.isNull(scenePlus)){
             throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
         }
+        SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
         SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByScenePlusId(scenePlus.getId());
 
         this.remove(new LambdaQueryWrapper<Surveillance>().eq(Surveillance::getSid, param.getSid()));
@@ -82,6 +91,9 @@ public class SurveillanceServiceImpl extends ServiceImpl<ISurveillanceMapper, Su
             sceneEditInfoExt.setSurveillances(CommonStatus.NO.code().intValue());
         }
         sceneEditInfoExtService.updateById(sceneEditInfoExt);
+
+        sceneEditInfoService.upgradeVersionById(sceneEditInfo.getId());
+
         return ResultData.ok();
     }
 

+ 29 - 0
src/main/java/com/fdkankan/scene/vo/BaseJsonArrayParamVO.java

@@ -0,0 +1,29 @@
+package com.fdkankan.scene.vo;
+
+import com.alibaba.fastjson.JSONArray;
+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.List;
+
+/**
+ * <p>
+ * 通用data类型参数类
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/2/10
+ **/
+@Data
+public class BaseJsonArrayParamVO extends BaseSceneParamVO{
+
+    @NotNull(message = "data不能为空")
+//    private List<LinkPanParamVO> linkPans;
+    private List<JSONObject> data;
+
+    private List<JSONObject> styles;
+
+}

+ 23 - 0
src/main/java/com/fdkankan/scene/vo/DeleteSidListParamVO.java

@@ -0,0 +1,23 @@
+package com.fdkankan.scene.vo;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+import java.util.List;
+
+/**
+ * <p>
+ * TODO
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/2/18
+ **/
+@Data
+public class DeleteSidListParamVO extends BaseSceneParamVO{
+
+    @NotEmpty(message = "sid不能为空")
+    private List<String> sidList;
+
+}

+ 1 - 4
src/main/java/com/fdkankan/scene/vo/DeleteLinkSceneStylesParamVO.java

@@ -14,10 +14,7 @@ import lombok.Data;
  * @since 2022/2/8
  **/
 @Data
-public class DeleteLinkSceneStylesParamVO {
-
-    @NotBlank(message = "场景码不能为空")
-    private String num;
+public class DeleteStylesParamVO extends BaseSceneParamVO{
 
     @NotNull(message = "sidList不能为空")
     private List<String> sidList;

+ 20 - 0
src/main/java/com/fdkankan/scene/vo/SceneEditControlsParamVO.java

@@ -97,6 +97,26 @@ public class SceneEditControlsParamVO implements Serializable {
      */
     private Integer showCapture;
 
+    /**
+     * 多媒体标签标题
+     */
+    private Integer showTagTitle;
+
+    /**
+     * 指示牌标签标题
+     */
+    private Integer showBillboardTitle;
+
+    /**
+     * 视频监控标签标题
+     */
+    private Integer showCameraTitle;
+
+    /**
+     * 场景关联标签标题
+     */
+    private Integer showLinkTitle;
+
 
 
 

+ 19 - 0
src/main/java/com/fdkankan/scene/vo/SceneEditControlsVO.java

@@ -87,5 +87,24 @@ public class SceneEditControlsVO implements Serializable {
      */
     private Integer showCapture;
 
+    /**
+     * 多媒体标签标题
+     */
+    private Integer showTagTitle;
+
+    /**
+     * 指示牌标签标题
+     */
+    private Integer showBillboardTitle;
+
+    /**
+     * 视频监控标签标题
+     */
+    private Integer showCameraTitle;
+
+    /**
+     * 场景关联标签标题
+     */
+    private Integer showLinkTitle;
 
 }

+ 6 - 0
src/main/java/com/fdkankan/scene/vo/SceneEditInfoParamVO.java

@@ -1,5 +1,6 @@
 package com.fdkankan.scene.vo;
 
+import com.alibaba.fastjson.JSONObject;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
@@ -73,6 +74,11 @@ public class SceneEditInfoParamVO extends BaseSceneParamVO{
 
     private SceneEditControlsParamVO controls;
 
+    /**
+     * 分享配置
+     */
+    private JSONObject sns;
+
 
 
 

+ 10 - 0
src/main/java/com/fdkankan/scene/vo/SceneInfoVO.java

@@ -234,5 +234,15 @@ public class SceneInfoVO {
      */
     private Integer space;
 
+    /**
+     * 分享信息
+     */
+    private JSONObject sns;
+
+    /**
+     * 是否有指示牌(0-否,1-是)
+     */
+    private Integer billboards;
+
 
 }

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

@@ -3,7 +3,7 @@ spring:
     name: 4dkankan-center-scene
   cloud:
     nacos:
-      server-addr: 172.31.42.151:8848
+      server-addr: 172.31.47.163:8848
       namespace: 4dkankan-v4-prod-eur
       config:
         file-extension: yaml

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

@@ -34,6 +34,7 @@ spring:
             refresh: true
       discovery:
         namespace: ${spring.cloud.nacos.namespace}
+#        namespace: public
 
 
 

+ 5 - 0
src/main/resources/mapper/scene/SceneCleanOrigMapper.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.scene.mapper.ISceneCleanOrigMapper">
+
+</mapper>

+ 5 - 0
src/main/resources/mapper/scene/SceneColdStorageLogMapper.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.scene.mapper.ISceneColdStorageLogMapper">
+
+</mapper>

+ 5 - 0
src/main/resources/mapper/scene/SceneColdStorageMapper.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.scene.mapper.ISceneColdStorageMapper">
+
+</mapper>

+ 42 - 1
src/main/resources/mapper/scene/ScenePlusMapper.xml

@@ -1,5 +1,46 @@
 <?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.com.fdkankan.scene.mapper.IScenePlusMapper">
+<mapper namespace="com.fdkankan.scene.mapper.IScenePlusMapper">
+
+    <select id="selectCleanOrigScene" resultType="com.fdkankan.scene.bean.SceneBean">
+        select plus.num, ext.data_source
+        from t_scene_plus plus
+        left join t_scene_plus_ext ext on plus.id = ext.plus_id
+        where plus.scene_status in (1,-2) and ext.algorithm_time <![CDATA[ < ]]> #{time}
+        and ext.data_source is NOT null
+        and NOT EXISTS (select o.num from t_scene_clean_orig o where o.rec_status = 'A' and o.num = plus.num and ext.algorithm_time <![CDATA[ < ]]> o.create_time)
+    </select>
+
+    <select id="selectCleanOrigSceneDeleted" resultType="com.fdkankan.scene.bean.SceneBean">
+        select plus.num, ext.data_source
+        from t_scene_plus plus
+        left join t_scene_plus_ext ext on plus.id = ext.plus_id
+        where plus.rec_status = 'I' and plus.update_time <![CDATA[ < ]]> #{time}
+        and ext.data_source is NOT null
+        and NOT EXISTS (select o.num from t_scene_clean_orig o where o.rec_status = 'A' and o.num = plus.num and o.type = 2)
+    </select>
+
+    <select id="listCleanOss4TestCamera" resultType="com.fdkankan.scene.bean.SceneBean">
+        select plus.num, ext.data_source
+        from t_scene_plus plus
+        left join t_scene_plus_ext ext on plus.id = ext.plus_id
+        where plus.scene_status in (1,-2) and plus.rec_status = 'A' and ext.algorithm_time <![CDATA[ < ]]> #{time}
+        and ext.data_source is NOT null
+        and plus.camera_id in
+        <foreach collection="cameraIds" item="cameraId" open="(" close=")" separator=",">
+            #{cameraId}
+        </foreach>
+        and NOT EXISTS (select o.num from t_scene_clean_orig o where o.rec_status = 'A' and o.num = plus.num and o.type = 3 and ext.algorithm_time <![CDATA[ < ]]> o.create_time)
+    </select>
+
+    <select id="selectColdStorageScene" resultType="com.fdkankan.scene.bean.SceneBean">
+        select plus.num, ext.data_source
+        from t_scene_plus plus
+        left join t_scene_plus_ext ext on plus.id = ext.plus_id
+        where plus.scene_status in (1,-2) and ext.algorithm_time <![CDATA[ < ]]> #{time}
+        and ext.data_source is NOT null
+        and NOT EXISTS (select c.num from t_scene_cold_storage c where c.rec_status = 'A' AND c.`state` = 1 and c.num = plus.num)
+        and NOT EXISTS (select o.num from t_scene_clean_orig o where o.rec_status = 'A' and o.state != -1 and o.num = plus.num and ext.algorithm_time <![CDATA[ < ]]> o.create_time)
+    </select>
 
 </mapper>

+ 39 - 1
src/main/resources/mapper/scene/SceneProMapper.xml

@@ -1,5 +1,43 @@
 <?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.com.fdkankan.scene.mapper.ISceneProMapper">
+<mapper namespace="com.fdkankan.scene.mapper.ISceneProMapper">
+
+    <select id="selectCleanOrigScene" resultType="com.fdkankan.scene.bean.SceneBean">
+        select pro.num, pro.data_source
+        from t_scene_pro pro
+        where pro.status in (1,-2) and pro.create_time <![CDATA[ < ]]> #{time}
+        and pro.data_source is not null
+        and NOT EXISTS (select o.num from t_scene_clean_orig o where o.rec_status = 'A' and o.num = pro.num and pro.create_time <![CDATA[ < ]]> o.create_time)
+    </select>
+
+    <select id="listCleanOss4DeletedScene" resultType="com.fdkankan.scene.bean.SceneBean">
+        select pro.num, pro.data_source
+        from t_scene_pro pro
+        where pro.rec_status = 'I' and pro.update_time <![CDATA[ < ]]> #{time}
+        and pro.data_source is not null
+        and NOT EXISTS (select o.num from t_scene_clean_orig o where o.rec_status = 'A' and o.num = pro.num and o.type = 2)
+    </select>
+
+    <select id="listCleanOss4TestCamera" resultType="com.fdkankan.scene.bean.SceneBean">
+        select pro.num, pro.data_source
+        from t_scene_pro pro
+        where pro.status in (1,-2) and pro.rec_status = 'A' and pro.create_time <![CDATA[ < ]]> #{time}
+        and pro.data_source is not null
+        and pro.camera_id in
+        <foreach collection="cameraIds" item="cameraId" open="(" close=")" separator=",">
+            #{cameraId}
+        </foreach>
+        and NOT EXISTS (select o.num from t_scene_clean_orig o where o.rec_status = 'A' and o.num = pro.num and o.type = 3 and pro.create_time <![CDATA[ < ]]> o.create_time)
+    </select>
+
+    <select id="selectColdStorageScene" resultType="com.fdkankan.scene.bean.SceneBean">
+        select pro.num, pro.data_source
+        from t_scene_pro pro
+        where pro.status in (1,-2) and pro.create_time <![CDATA[ < ]]> #{time}
+        and pro.data_source is not null
+        and pro.is_upgrade = 0
+        and NOT EXISTS (select c.num from t_scene_cold_storage c where c.rec_status = 'A' and c.state = 1 and c.num = pro.num)
+        and NOT EXISTS (select o.num from t_scene_clean_orig o where o.rec_status = 'A' and o.state != -1 and o.num = pro.num and pro.create_time <![CDATA[ < ]]> o.create_time)
+    </select>
 
 </mapper>

+ 0 - 23
src/test/java/com/fdkankan/scene/SceneApplicationTests.java

@@ -1,23 +0,0 @@
-package com.fdkankan.scene;
-
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.context.SpringBootTest;
-
-@SpringBootTest
-class ApplicationTests {
-
-    @Test
-    void contextLoads() {
-    }
-
-
-
-    @Test
-    public String test2() throws Exception {
-
-
-        return "123";
-
-    }
-
-}