dengsixing 1 year ago
parent
commit
2942825d7b
33 changed files with 2437 additions and 209 deletions
  1. 29 9
      pom.xml
  2. 15 3
      src/main/java/com/fdkankan/project/tieta/Application.java
  3. 4 0
      src/main/java/com/fdkankan/project/tieta/bean/ResultData.java
  4. 12 0
      src/main/java/com/fdkankan/project/tieta/bean/TietaResBean.java
  5. 22 0
      src/main/java/com/fdkankan/project/tieta/config/MybatisPlusPageConfig.java
  6. 2 0
      src/main/java/com/fdkankan/project/tieta/constant/Constant.java
  7. 3 1
      src/main/java/com/fdkankan/project/tieta/constant/ServerCode.java
  8. 118 4
      src/main/java/com/fdkankan/project/tieta/controller/ConvertController.java
  9. 39 0
      src/main/java/com/fdkankan/project/tieta/controller/SceneController.java
  10. 21 0
      src/main/java/com/fdkankan/project/tieta/dto/ScenePushDTO.java
  11. 132 0
      src/main/java/com/fdkankan/project/tieta/entity/FullphotoFileindex.java
  12. 2 2
      src/main/java/com/fdkankan/project/tieta/entity/Scene.java
  13. 2 2
      src/main/java/com/fdkankan/project/tieta/entity/UserInfo.java
  14. 101 0
      src/main/java/com/fdkankan/project/tieta/generator/AutoGenerate.java
  15. 186 182
      src/main/java/com/fdkankan/project/tieta/generator/MappingGeneratorOracle.java
  16. 22 0
      src/main/java/com/fdkankan/project/tieta/mapper/FullphotoFileindexMapper.java
  17. 26 0
      src/main/java/com/fdkankan/project/tieta/service/FullphotoFileindexService.java
  18. 6 0
      src/main/java/com/fdkankan/project/tieta/service/IConvertService.java
  19. 71 2
      src/main/java/com/fdkankan/project/tieta/service/impl/ConvertServiceImpl.java
  20. 39 0
      src/main/java/com/fdkankan/project/tieta/service/impl/FullphotoFileindexServiceImpl.java
  21. 113 0
      src/main/java/com/fdkankan/project/tieta/utils/FdfsUtil.java
  22. 40 0
      src/main/java/com/fdkankan/rabbitmq/callback/ProducerCallback.java
  23. 119 0
      src/main/java/com/fdkankan/rabbitmq/config/RabbitMqConfig.java
  24. 112 0
      src/main/java/com/fdkankan/rabbitmq/util/RabbitMqProducer.java
  25. 44 0
      src/main/java/com/fdkankan/redis/config/RedisConfig.java
  26. 225 0
      src/main/java/com/fdkankan/redis/constant/RedisKey.java
  27. 192 0
      src/main/java/com/fdkankan/redis/constant/RedisLockKey.java
  28. 145 0
      src/main/java/com/fdkankan/redis/util/RedisLockUtil.java
  29. 498 0
      src/main/java/com/fdkankan/redis/util/RedisUtil.java
  30. 47 0
      src/main/resources/application-dev.yml
  31. 15 3
      src/main/resources/application-test.yml
  32. 1 1
      src/main/resources/logback-spring.xml
  33. 34 0
      src/main/resources/mapper/FullphotoFileindexMapper.xml

+ 29 - 9
pom.xml

@@ -74,12 +74,6 @@
     </dependency>
 
     <dependency>
-      <groupId>com.fdkankan</groupId>
-      <artifactId>4dkankan-utils-rabbitmq</artifactId>
-      <version>3.0.0-SNAPSHOT</version>
-    </dependency>
-
-    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
     </dependency>
@@ -110,14 +104,14 @@
     <dependency>
       <groupId>com.baomidou</groupId>
       <artifactId>mybatis-plus-boot-starter</artifactId>
-      <version>3.0.5</version>
+      <version>3.4.3.4</version>
     </dependency>
 
     <!-- mybatis-plus逆向工程依赖 -->
     <dependency>
       <groupId>com.baomidou</groupId>
       <artifactId>mybatis-plus-generator</artifactId>
-      <version>3.2.0</version>
+      <version>3.5.1</version>
     </dependency>
 
     <!-- freemarker 说明:mybatis-plus逆向工程需要freemarker模板引擎 -->
@@ -126,7 +120,33 @@
       <artifactId>freemarker</artifactId>
     </dependency>
 
+    <!--velocity模板-->
+    <dependency>
+      <groupId>org.apache.velocity</groupId>
+      <artifactId>velocity-engine-core</artifactId>
+      <version>2.3</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-amqp</artifactId>
+      <version>2.3.12.RELEASE</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-data-redis</artifactId>
+      <version>2.3.12.RELEASE</version>
+    </dependency>
 
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-pool2</artifactId>
+    </dependency>
 
   </dependencies>
 
@@ -162,7 +182,7 @@
 <!--        </configuration>-->
 <!--      </plugin>-->
 <!--    </plugins>-->
-    <finalName>4dkankan-center-push</finalName>
+    <finalName>scene-push</finalName>
     <plugins>
       <plugin>
         <groupId>org.springframework.boot</groupId>

+ 15 - 3
src/main/java/com/fdkankan/project/tieta/Application.java

@@ -1,21 +1,33 @@
-package com.fdkankan.project.tieta;
+package com.fdkankan;
 
+import com.fdkankan.project.tieta.service.IConvertService;
 import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.context.annotation.ComponentScan;
+import org.springframework.core.convert.ConversionService;
 import org.springframework.scheduling.annotation.EnableAsync;
 import org.springframework.scheduling.annotation.EnableScheduling;
 
 @SpringBootApplication
 @EnableScheduling
-@ComponentScan(basePackages = {"com.fdkankan.*"})
 @EnableAsync
 @MapperScan("com.fdkankan.project.tieta.mapper")
-public class Application {
+public class Application implements CommandLineRunner {
+
+    @Autowired
+    private IConvertService convertService;
+
     public static void main(String[] args) {
         SpringApplication.run(Application.class, args);
     }
+
+    @Override
+    public void run(String... args) throws Exception {
+        convertService.scenePushHistory();
+    }
 }
 
 

+ 4 - 0
src/main/java/com/fdkankan/project/tieta/bean/ResultData.java

@@ -59,4 +59,8 @@ public class ResultData<T> implements Serializable {
         return rd;
     }
 
+    public static ResultData error(ServerCode errorCode) {
+        return error(errorCode.code(), errorCode.message());
+    }
+
 }

+ 12 - 0
src/main/java/com/fdkankan/project/tieta/bean/TietaResBean.java

@@ -0,0 +1,12 @@
+package com.fdkankan.project.tieta.bean;
+
+import lombok.Data;
+
+@Data
+public class TietaResBean<T> {
+
+    private String code;
+    private String mes;
+    private T data;
+
+}

+ 22 - 0
src/main/java/com/fdkankan/project/tieta/config/MybatisPlusPageConfig.java

@@ -0,0 +1,22 @@
+package com.fdkankan.project.tieta.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+
+@Configuration
+public class MybatisPlusPageConfig {
+
+    /**
+     * mybatisPlus配置分页插件
+     */
+    @Bean
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.ORACLE));
+        return interceptor;
+    }
+}

+ 2 - 0
src/main/java/com/fdkankan/project/tieta/constant/Constant.java

@@ -4,4 +4,6 @@ public class Constant {
 
     public static final String QUEUE_SCENE_CONVERT = "queue-scene-convert";
 
+    public static final String REDIS_SCENE_CONVERT_HISTORY = "scene:convert:history";
+
 }

+ 3 - 1
src/main/java/com/fdkankan/project/tieta/constant/ServerCode.java

@@ -9,7 +9,9 @@ public enum ServerCode {
 	FEIGN_REQUEST_FAILD(-4, "跨服务请求失败"),
 	SERVER_CLOSING(-5, "服务正在关闭!"),
 
-	APP_ID_ILLEGAL(3100, "非法的APP ID");
+	APP_ID_ILLEGAL(3100, "非法的APP ID"),
+
+	RESOURCE_NOT_EXIST(1000, "资源不存在");
 
 	private Integer code;
 	private String message;

+ 118 - 4
src/main/java/com/fdkankan/project/tieta/controller/ConvertController.java

@@ -1,14 +1,23 @@
 package com.fdkankan.project.tieta.controller;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.fdkankan.project.tieta.bean.ResultData;
 import com.fdkankan.project.tieta.dto.SendConvertDTO;
+import com.fdkankan.project.tieta.dto.ScenePushDTO;
+import com.fdkankan.project.tieta.entity.FullphotoFileindex;
+import com.fdkankan.project.tieta.service.FullphotoFileindexService;
 import com.fdkankan.project.tieta.service.IConvertService;
+import com.fdkankan.project.tieta.utils.FdfsUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.File;
+import java.util.*;
 
 @RestController
 @RequestMapping("/convert")
@@ -23,5 +32,110 @@ public class ConvertController {
         return ResultData.ok();
     }
 
+    @PostMapping("/push")
+    public ResultData push(@RequestBody @Validated ScenePushDTO dto){
+        return convertService.scenePush(dto);
+    }
+
+    @GetMapping("/pushHistory")
+    public ResultData pushHistory(){
+        convertService.scenePushHistory();
+        return ResultData.ok();
+    }
+
+    @Autowired
+    FullphotoFileindexService fullphotoFileindexService;
+    @GetMapping("/pushHistory2")
+    public ResultData pushHistory2(){
+//        List<FullphotoFileindex> fullphotoFileindices = null;
+//        long current = 1;
+//        int size = 1;
+//        Page<FullphotoFileindex> fullphotoFileindexPage = null;
+//        do {
+//            fullphotoFileindexPage = fullphotoFileindexService.pageStationCodeAndEntityId(current, size);
+//            fullphotoFileindices = fullphotoFileindexPage.getRecords();
+//        }while (fullphotoFileindexPage.hasNext());
+//
+//        return ResultData.ok();
+        IPage<FullphotoFileindex> page = fullphotoFileindexService.page(new Page<>(1, 100));
+        return ResultData.ok();
+
+    }
+
+    @GetMapping("/pushDemo")
+    public ResultData pushDemo(){
+        String path  = "D:\\test\\tieta\\50个全景制品数据包\\";
+        List<File> files = FileUtil.loopFiles(path);
+        Set<String> stationCodeRoomIdSet = new HashSet<>();
+        for (File file : files) {
+            String absolutePath = file.getAbsolutePath();
+            String replace = absolutePath.replace(path, "");
+            String substring = replace.substring(0, replace.indexOf("\\"));
+            stationCodeRoomIdSet.add(substring);
+        }
+
+        for (String item : stationCodeRoomIdSet) {
+            String[] split = item.split("_");
+            String stationCode = split[0];
+            String entityId = split[1];
+            List<File> files1 = FileUtil.loopFiles(path + item);
+            for (File file : files1) {
+                String fileAbsolutePath = file.getAbsolutePath();
+                String fileType = null;
+                if(!file.isDirectory()){
+                    if(fileAbsolutePath.contains("vision.txt")){
+                        fileType = "7";
+                    }
+                    if(fileAbsolutePath.contains("512")){
+                        fileType = "1";
+                    }
+                    if(fileAbsolutePath.contains("4k")){
+                        fileType = "2";
+                    }
+                    if(fileAbsolutePath.contains("8k")){
+                        fileType = "3";
+                    }
+                    if(fileAbsolutePath.contains("mesh.obj")){
+                        fileType = "11";
+                    }
+                    if(fileAbsolutePath.contains("floorplan.json")){
+                        fileType = "5";
+                    }
+                    if(fileAbsolutePath.contains("scene.json")){
+                        fileType = "12";
+                    }
+                    if(StrUtil.isNotEmpty(fileType)){
+                        Map<String, String> stringStringMap = fdfsUtil.uploadFile(file.getAbsolutePath());
+                        String fileId = stringStringMap.get("file_id");
+                        String httpUrl = stringStringMap.get("http_url");
+                        FullphotoFileindex fullphotoFileindex = new FullphotoFileindex();
+                        fullphotoFileindex.setStationCode(stationCode);
+                        fullphotoFileindex.setEntityId(entityId);
+                        fullphotoFileindex.setFileid(fileId);
+                        fullphotoFileindex.setFileUrl(httpUrl);
+                        fullphotoFileindex.setFileName(file.getName());
+                        fullphotoFileindex.setStatus("1");
+                        fullphotoFileindex.setFileType(fileType);
+                        fullphotoFileindexService.save(fullphotoFileindex);
+                    }
+
+                }
+            }
+
+        }
+
+
+        return ResultData.ok();
+
+    }
+
+    @Autowired
+    private FdfsUtil fdfsUtil;
+
+    public static void main(String[] args) {
+
+
+    }
+
 
 }

+ 39 - 0
src/main/java/com/fdkankan/project/tieta/controller/SceneController.java

@@ -1,15 +1,25 @@
 package com.fdkankan.project.tieta.controller;
 
 
+import cn.hutool.core.img.ImgUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.http.HttpUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.fdkankan.project.tieta.bean.ResultData;
+import com.fdkankan.project.tieta.entity.FullphotoFileindex;
 import com.fdkankan.project.tieta.entity.Scene;
+import com.fdkankan.project.tieta.service.FullphotoFileindexService;
 import com.fdkankan.project.tieta.service.SceneService;
+import com.fdkankan.project.tieta.utils.CreateObjUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 import org.springframework.web.bind.annotation.RestController;
 
+import java.io.File;
+import java.util.List;
+
 /**
  * <p>
  *  前端控制器
@@ -38,5 +48,34 @@ public class SceneController {
         return  ResultData.ok();
     }
 
+    @Autowired
+    private FullphotoFileindexService fullphotoFileindexService;
+
+    @GetMapping("/test2")
+    public ResultData test2(String stationCode, String roomEntityID) throws Exception {
+
+        String path = "D:\\test\\tieta\\" + stationCode + "_" + roomEntityID + "\\";
+        List<FullphotoFileindex> list = fullphotoFileindexService.list(new LambdaQueryWrapper<FullphotoFileindex>().eq(FullphotoFileindex::getStationCode, stationCode).eq(FullphotoFileindex::getEntityId, roomEntityID));
+        list.stream().forEach(v->{
+            String localPath = path + v.getFileName();
+            HttpUtil.downloadFile(v.getFileUrl(), localPath);
+            if(v.getFileName().endsWith("jpg")){
+                String highPath = path + "pan\\high\\" + v.getFileName();
+                FileUtil.mkParentDirs(highPath);
+                String lowPath = path + "pan\\low\\" + v.getFileName();
+                FileUtil.mkParentDirs(lowPath);
+                ImgUtil.scale(new File(localPath),new File(highPath), 0.5f);
+                ImgUtil.scale(new File(localPath),new File(lowPath), 0.0625f);
+
+            }
+        });
+
+        CreateObjUtil.convertTxtToVisionmodeldata(path + "vision.txt", path + "vision.modeldata");
+
+        return  ResultData.ok();
+    }
+
+
+
 
 }

+ 21 - 0
src/main/java/com/fdkankan/project/tieta/dto/ScenePushDTO.java

@@ -0,0 +1,21 @@
+package com.fdkankan.project.tieta.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotBlank;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ScenePushDTO {
+
+    @NotBlank(message = "stationCode不能为空")
+    private String stationCode;
+
+    @NotBlank(message = "entityId不能为空")
+    private String entityId;
+}

+ 132 - 0
src/main/java/com/fdkankan/project/tieta/entity/FullphotoFileindex.java

@@ -0,0 +1,132 @@
+package com.fdkankan.project.tieta.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.util.Date;
+
+/**
+ * <p>
+ *
+ * </p>
+ *
+ * @author dsx
+ * @since 2024-07-01
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@TableName("T_FULLPHOTO_FILEINDEX")
+public class FullphotoFileindex extends Model<FullphotoFileindex> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 省分
+     */
+    @TableField("PROVINCE_ID")
+    private String provinceId;
+
+    /**
+     * 地市
+     */
+    @TableField("REGION_ID")
+    private String regionId;
+
+    /**
+     * 站址编码
+     */
+    @TableField("STATION_CODE")
+    private String stationCode;
+
+    /**
+     * 机房ID
+     */
+    @TableField("ENTITY_ID")
+    private String entityId;
+
+    /**
+     * 文件名称
+     */
+    @TableField("FILE_NAME")
+    private String fileName;
+
+    /**
+     * 文件md5码
+     */
+    @TableField("FILE_MD5")
+    private String fileMd5;
+
+    /**
+     * 文件类型(1-512图片,2-4K图片,3-8K图片,5-小地图文件,7-点位文件,11-模型文件,12-场景信息文件(可根据实际增加枚举值))
+     */
+    @TableField("FILE_TYPE")
+    private String fileType;
+
+    /**
+     * 点位Uuid
+     */
+    @TableField("PIC_UUID")
+    private String picUuid;
+
+    /**
+     * 上传时间
+     */
+    @TableField("UP_TIME")
+    private Date upTime;
+
+    /**
+     * 上传用户
+     */
+    @TableField("UP_USER")
+    private String upUser;
+
+    /**
+     * 文件大小
+     */
+    @TableField("FILE_SIZE")
+    private String fileSize;
+
+    /**
+     * 文件标识fileID
+     */
+    @TableField("FILEID")
+    private String fileid;
+
+    /**
+     * 记录唯一ID
+     */
+    @TableField("RECORD_ID")
+    private String recordId;
+
+    /**
+     * 上传记录id
+     */
+    @TableField("UPLOAD_ID")
+    private String uploadId;
+
+    /**
+     * 状态: 1-正常 2-已删除 3-删除失败
+     */
+    @TableField("STATUS")
+    private String status;
+
+    /**
+     * 分布式存储文件下载URL
+     */
+    @TableField("FILE_URL")
+    private String fileUrl;
+
+
+    @Override
+    public Serializable pkVal() {
+        return null;
+    }
+
+}

+ 2 - 2
src/main/java/com/fdkankan/project/tieta/entity/Scene.java

@@ -12,7 +12,7 @@ import lombok.experimental.Accessors;
 
 /**
  * <p>
- * 
+ *
  * </p>
  *
  * @author dsx
@@ -58,7 +58,7 @@ public class Scene extends Model<Scene> {
 
 
     @Override
-    protected Serializable pkVal() {
+    public Serializable pkVal() {
         return this.id;
     }
 

+ 2 - 2
src/main/java/com/fdkankan/project/tieta/entity/UserInfo.java

@@ -12,7 +12,7 @@ import lombok.experimental.Accessors;
 
 /**
  * <p>
- * 
+ *
  * </p>
  *
  * @author dsx
@@ -37,7 +37,7 @@ public class UserInfo extends Model<UserInfo> {
 
 
     @Override
-    protected Serializable pkVal() {
+    public Serializable pkVal() {
         return this.id;
     }
 

+ 101 - 0
src/main/java/com/fdkankan/project/tieta/generator/AutoGenerate.java

@@ -0,0 +1,101 @@
+package com.fdkankan.project.tieta.generator;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.generator.FastAutoGenerator;
+import com.baomidou.mybatisplus.generator.config.OutputFile;
+import com.baomidou.mybatisplus.generator.config.rules.DateType;
+import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public class AutoGenerate {
+
+
+    public static void main(String[] args) {
+
+        String path =System.getProperty("user.dir");
+
+        generate(path,"project.tieta.generator", getTables(new String[]{
+                "T_FULLPHOTO_UPRECORD"
+        }));
+
+//        generate(path,"goods", getTables(new String[]{
+//                        "t_camera","t_camera_detail","t_camera_out","t_camera_space","t_camera_version",
+//                        "t_company","t_goods","t_goods_sku","t_cart","t_goods_spec",
+//                        "t_goods_spec_value","t_goods_spu_spec","t_sn_code"
+//        }));
+//
+//        generate(path,"order", getTables(new String[]{
+//                        "t_increment_order","t_invoice","t_order","t_order_item",
+//                        "t_pre_sale","t_space_sdk","t_trade_log","t_commerce_order","t_download_order","t_expansion_order"
+//        }));
+//        generate(path,"order", getTables(new String[]{
+//                        "t_virtual_order"
+//        }));
+//
+//        generate(path,"user", getTables(new String[]{
+//                        "t_user","t_user_increment","t_manager","t_province","t_increment_type","t_intercom_message","t_receiver_info"
+//        }));
+    }
+
+    public static List<String> getTables(String [] tableNames){
+        return new ArrayList<>(Arrays.asList(tableNames));
+    }
+
+
+    public static void  generate(String path,String moduleName,  List<String> tables){
+        FastAutoGenerator.create("jdbc:oracle:thin:@//10.180.41.37:1521/resdb",
+            "RES_FILE","qNQVkH3YbA")
+                .globalConfig(builder -> {
+                    builder.author("")               //作者
+                            .outputDir(path+"\\src\\main\\java")    //输出路径(写到java目录)
+                            //.enableSwagger()           //开启swagger
+                            .commentDate("yyyy-MM-dd")
+                            .dateType(DateType.ONLY_DATE)
+                            .fileOverride();            //开启覆盖之前生成的文件
+
+                })
+                .packageConfig(builder -> {
+                    builder.parent("com.fdkankan")
+                            .moduleName(moduleName)
+                            .entity("entity")
+                            .service("service")
+                            .serviceImpl("service.impl")
+                            .controller("controller")
+                            .mapper("mapper")
+                            .xml("test.mapper")
+                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml,path+"\\src\\main\\resources\\mapper\\"+moduleName));
+                })
+                .strategyConfig(builder -> {
+                    builder.addInclude(tables)
+                            .addTablePrefix("t_")
+
+                            .serviceBuilder()
+                            .formatServiceFileName("%sService")
+                            .formatServiceImplFileName("%sServiceImpl")
+
+                            .entityBuilder()
+                            .enableLombok()
+                            .logicDeleteColumnName("rec_status")
+                            .enableTableFieldAnnotation()
+                            .idType(IdType.AUTO)
+//                            .superClass(BaseEntity.class)
+
+                            .controllerBuilder()
+                            .formatFileName("%sController")
+                            .enableRestStyle()
+
+                            .mapperBuilder()
+                            .superClass(BaseMapper.class)
+                            .formatMapperFileName("%sMapper")
+                            .enableMapperAnnotation()
+                            .formatXmlFileName("%sMapper");
+                })
+//                 .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
+                .execute();
+    }
+}

+ 186 - 182
src/main/java/com/fdkankan/project/tieta/generator/MappingGeneratorOracle.java

@@ -1,185 +1,189 @@
-package com.fdkankan.project.tieta.generator;
-
-import com.baomidou.mybatisplus.annotation.DbType;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.generator.AutoGenerator;
-import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
-import com.baomidou.mybatisplus.generator.config.GlobalConfig;
-import com.baomidou.mybatisplus.generator.config.PackageConfig;
-import com.baomidou.mybatisplus.generator.config.StrategyConfig;
-import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
-import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
-import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
-
-/**
- * 代码生成器
- *
- * <p>
- * 根据数据库中的表生成:数据库表映射对象、Mapper 接口、Mapper XML 文件(含基础的 ResultMap 和字段代码片段)、 Service
- * 接口、Service 接口实现累、基础的 Controller 类。
- * </p>
- * <p>
- * 如果数据库设计符合规范,并且代码没有特殊要求。设置好表名前缀(无则忽略)、表字段前缀(无则忽略)后, 直接修改输出的路径、JDBC
- * Url、数据库的账户和密码即可直接生成代码。
- * </p>
- * <p>
- * 生成后将 Mapper 中的 xml 包中的 XML 文件移动到 resource 下即可,XML 存放文件夹名为 Mapper
- * 接口包名(全包名)的同名文件夹<br/>
- * 如 Mapper 接口包名为:com.example.mapper,那么在 resource 下新建同名文件夹:com.example.mapper,将
- * xml 文件移动到该文件夹下即可。
- * </p>
- *
- * @author wayne
- * @since 2020-01-08 23:00
- */
-public class MappingGeneratorOracle {
-
-	/**
-	 * 生成代码输出路径,<strong>路径必须是绝对路径,不需要包含包名</strong>
-	 */
-	private static final String OUTPUT_DIR = ".\\src\\main\\java\\com\\fdkankan\\project\\tieta\\generator";
-	/**
-	 * 生成代码输出的包名
-	 * <p>
-	 * 总包名,后续生成的 Mapper,Service 等将在该包下生成子包
-	 * </p>
-	 */
-	private static final String PACKAGE = "com.fdkankan.project.tieta";
-	/**
-	 * JDBC URL 说明: url地址前需要加上@,否则会报错
-	 */
-
-	private static final String JDBC_URL = "jdbc:oracle:thin:@//8.135.106.227:1521/helowin";
-	/**
-	 * 数据库账户
-	 */
-	private static final String DB_USERNAME = "FDKK";
-	/**
-	 * 数据库账户密码
-	 */
-	private static final String DB_PASSWORD = "qawsed@123.";
-
-	/**
-	 * 执行即可生成代码 需要添加 freemarker 依赖 <dependency> <groupId>org.freemarker</groupId>
-	 * <artifactId>freemarker</artifactId> <version>2.3.29</version> </dependency>
-	 */
-	// 不要在src/main/java里面使用main方法,否则springboot项目某人为main方法的类就是启动类
+//package com.fdkankan.project.tieta.generator;
+//
+//import com.baomidou.mybatisplus.annotation.DbType;
+//import com.baomidou.mybatisplus.annotation.IdType;
+//import com.baomidou.mybatisplus.generator.AutoGenerator;
+//import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
+//import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+//import com.baomidou.mybatisplus.generator.config.PackageConfig;
+//import com.baomidou.mybatisplus.generator.config.StrategyConfig;
+//import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
+//import com.baomidou.mybatisplus.generator.config.rules.DateType;
+//import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
+//import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
+//
+///**
+// * 代码生成器
+// *
+// * <p>
+// * 根据数据库中的表生成:数据库表映射对象、Mapper 接口、Mapper XML 文件(含基础的 ResultMap 和字段代码片段)、 Service
+// * 接口、Service 接口实现累、基础的 Controller 类。
+// * </p>
+// * <p>
+// * 如果数据库设计符合规范,并且代码没有特殊要求。设置好表名前缀(无则忽略)、表字段前缀(无则忽略)后, 直接修改输出的路径、JDBC
+// * Url、数据库的账户和密码即可直接生成代码。
+// * </p>
+// * <p>
+// * 生成后将 Mapper 中的 xml 包中的 XML 文件移动到 resource 下即可,XML 存放文件夹名为 Mapper
+// * 接口包名(全包名)的同名文件夹<br/>
+// * 如 Mapper 接口包名为:com.example.mapper,那么在 resource 下新建同名文件夹:com.example.mapper,将
+// * xml 文件移动到该文件夹下即可。
+// * </p>
+// *
+// * @author wayne
+// * @since 2020-01-08 23:00
+// */
+//public class MappingGeneratorOracle {
+//
+//	/**
+//	 * 生成代码输出路径,<strong>路径必须是绝对路径,不需要包含包名</strong>
+//	 */
+//	private static final String OUTPUT_DIR = ".\\src\\main\\java\\com\\fdkankan\\project\\tieta\\generator";
+//	/**
+//	 * 生成代码输出的包名
+//	 * <p>
+//	 * 总包名,后续生成的 Mapper,Service 等将在该包下生成子包
+//	 * </p>
+//	 */
+//	private static final String PACKAGE = "com.fdkankan.project.tieta";
+//	/**
+//	 * JDBC URL 说明: url地址前需要加上@,否则会报错
+//	 */
+//
+//	private static final String JDBC_URL = "jdbc:oracle:thin:@//10.180.41.37:1521/resdb";
+//	/**
+//	 * 数据库账户
+//	 */
+//	private static final String DB_USERNAME = "RES_FILE";
+//	/**
+//	 * 数据库账户密码
+//	 */
+//	private static final String DB_PASSWORD = "qNQVkH3YbA";
+//
+//	/**
+//	 * 执行即可生成代码 需要添加 freemarker 依赖 <dependency> <groupId>org.freemarker</groupId>
+//	 * <artifactId>freemarker</artifactId> <version>2.3.29</version> </dependency>
+//	 */
+//	// 不要在src/main/java里面使用main方法,否则springboot项目某人为main方法的类就是启动类
+////	public static void main(String[] args) {
+////		autoGenerator().execute();
+////	}
+//
+//	public static AutoGenerator autoGenerator() {
+//		AutoGenerator autoGenerator = new AutoGenerator();
+//		autoGenerator.setGlobalConfig(globalConfig());
+//		autoGenerator.setDataSource(oracleDataSourceConfig());
+//		autoGenerator.setStrategy(strategyConfig());
+//		autoGenerator.setPackageInfo(packageConfig());
+//		autoGenerator.setTemplateEngine(new FreemarkerTemplateEngine());
+//		return autoGenerator;
+//	}
+//
 //	public static void main(String[] args) {
 //		autoGenerator().execute();
 //	}
-
-	public static AutoGenerator autoGenerator() {
-		AutoGenerator autoGenerator = new AutoGenerator();
-		autoGenerator.setGlobalConfig(globalConfig());
-		autoGenerator.setDataSource(oracleDataSourceConfig());
-		autoGenerator.setStrategy(strategyConfig());
-		autoGenerator.setPackageInfo(packageConfig());
-		autoGenerator.setTemplateEngine(new FreemarkerTemplateEngine());
-		return autoGenerator;
-	}
-
-	public static void main(String[] args) {
-		autoGenerator().execute();
-	}
-
-	/**
-	 * 全局配置
-	 *
-	 * @return {@link GlobalConfig}
-	 */
-	private static GlobalConfig globalConfig() {
-		GlobalConfig globalConfig = new GlobalConfig();
-		globalConfig.setAuthor("dsx");
-		// 设置代码输出位置,需要绝对路径
-		globalConfig.setOutputDir(OUTPUT_DIR);
-		// 覆盖已有的代码
-		globalConfig.setFileOverride(false);
-		// 基本表的 ResultMap
-		globalConfig.setBaseResultMap(true);
-		// 基本表字段片段
-		globalConfig.setBaseColumnList(true);
-		// 开启基于 Model 操作数据库
-		globalConfig.setActiveRecord(true);
-		// 设置 ID 类型
-		globalConfig.setIdType(IdType.AUTO);
-//		// 生成基本 Swagger2 文档
-//		globalConfig.setSwagger2(true);
-		// 开启二级缓存
-//		globalConfig.setEnableCache(true);
-		// 设置生成的对象名称规则,%s 表示当前的 Entity
-		// 数据库表映射对象名称规则
-		globalConfig.setEntityName("%s");
-		// 也可以使用下面这种就是末尾会以DO结尾
-//		globalConfig.setEntityName("%sDO");
-		// Mapper 接口名称规则
-		globalConfig.setMapperName("%sMapper");
-		// Mapper XML 文件名称规则
-		globalConfig.setXmlName("%sMapper");
-		// Controller 生成规则
-		globalConfig.setControllerName("%sController");
-		// Service 接口生成名称规则
-		globalConfig.setServiceName("%sService");
-		// Service 实现类生成名称规则
-		globalConfig.setServiceImplName("%sServiceImpl");
-		return globalConfig;
-	}
-
-	/**
-	 * 生成策略配置
-	 *
-	 * @return StrategyConfig
-	 */
-	private static StrategyConfig strategyConfig() {
-		StrategyConfig strategyConfig = new StrategyConfig();
-		strategyConfig.setCapitalMode(false);
-		strategyConfig.setEntityLombokModel(true);
-		strategyConfig.setRestControllerStyle(true);
-		strategyConfig.setNaming(NamingStrategy.underline_to_camel);
-		strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
-		// TODO 填写表前缀、表字段前缀,生成代码时去除字段前缀
-		strategyConfig.setTablePrefix("t_");
-		strategyConfig.setFieldPrefix("a_", "c_", "e_", "f_", "p_", "r_", "t_", "tf_");
-		return strategyConfig;
-	}
-
-	/**
-	 * MySQL 数据源配置
-	 *
-	 * @return DataSourceConfig
-	 */
-	private static DataSourceConfig oracleDataSourceConfig() {
-		DataSourceConfig dataSourceConfig = new DataSourceConfig();
-		dataSourceConfig.setDbType(DbType.ORACLE);
-		dataSourceConfig.setTypeConvert(new MySqlTypeConvert());
-		dataSourceConfig.setDriverName("oracle.jdbc.driver.OracleDriver");
-		dataSourceConfig.setUrl(JDBC_URL);
-		dataSourceConfig.setUsername(DB_USERNAME);
-		dataSourceConfig.setPassword(DB_PASSWORD);
-		return dataSourceConfig;
-	}
-
-	/**
-	 * 包相关配置信息
-	 * <p>
-	 * 配置生成代码的包信息,如生成的 Mapper 包,Service 包等
-	 * </p>
-	 */
-	private static PackageConfig packageConfig() {
-		PackageConfig packageConfig = new PackageConfig();
-		// 设置父包
-		packageConfig.setParent(PACKAGE);
-		// TODO 设置生成代码的包
-		// Controller 包
-		packageConfig.setController("controller");
-		// 数据库表映射对象包
-		packageConfig.setEntity("entity");
-		// Mapper 接口包,含 XML 文件
-		packageConfig.setMapper("mapper");
-		// Service 接口包
-		packageConfig.setService("service");
-		// Service 接口实现类包
-		packageConfig.setServiceImpl("service.impl");
-		return packageConfig;
-	}
-}
-
+//
+//	/**
+//	 * 全局配置
+//	 *
+//	 * @return {@link GlobalConfig}
+//	 */
+//	private static GlobalConfig globalConfig() {
+//		GlobalConfig globalConfig = new GlobalConfig();
+//		globalConfig.setAuthor("dsx");
+//		// 设置代码输出位置,需要绝对路径
+//		globalConfig.setOutputDir(OUTPUT_DIR);
+//		// 覆盖已有的代码
+//		globalConfig.setFileOverride(false);
+//		// 基本表的 ResultMap
+//		globalConfig.setBaseResultMap(true);
+//		// 基本表字段片段
+//		globalConfig.setBaseColumnList(true);
+//		// 开启基于 Model 操作数据库
+//		globalConfig.setActiveRecord(true);
+//		//
+//		globalConfig.setDateType(DateType.ONLY_DATE);
+//		// 设置 ID 类型
+//		globalConfig.setIdType(IdType.AUTO);
+////		// 生成基本 Swagger2 文档
+////		globalConfig.setSwagger2(true);
+//		// 开启二级缓存
+////		globalConfig.setEnableCache(true);
+//		// 设置生成的对象名称规则,%s 表示当前的 Entity
+//		// 数据库表映射对象名称规则
+//		globalConfig.setEntityName("%s");
+//		// 也可以使用下面这种就是末尾会以DO结尾
+////		globalConfig.setEntityName("%sDO");
+//		// Mapper 接口名称规则
+//		globalConfig.setMapperName("%sMapper");
+//		// Mapper XML 文件名称规则
+//		globalConfig.setXmlName("%sMapper");
+//		// Controller 生成规则
+//		globalConfig.setControllerName("%sController");
+//		// Service 接口生成名称规则
+//		globalConfig.setServiceName("%sService");
+//		// Service 实现类生成名称规则
+//		globalConfig.setServiceImplName("%sServiceImpl");
+//		return globalConfig;
+//	}
+//
+//	/**
+//	 * 生成策略配置
+//	 *
+//	 * @return StrategyConfig
+//	 */
+//	private static StrategyConfig strategyConfig() {
+//		StrategyConfig strategyConfig = new StrategyConfig();
+//		strategyConfig.setCapitalMode(false);
+//		strategyConfig.setEntityLombokModel(true);
+//		strategyConfig.setRestControllerStyle(true);
+//		strategyConfig.setNaming(NamingStrategy.underline_to_camel);
+//		strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
+//		// TODO 填写表前缀、表字段前缀,生成代码时去除字段前缀
+//		strategyConfig.setTablePrefix("t_");
+//		strategyConfig.setFieldPrefix("a_", "c_", "e_", "f_", "p_", "r_", "t_", "tf_");
+//		strategyConfig.setInclude("T_FULLPHOTO_FILEINDEX");
+//		return strategyConfig;
+//	}
+//
+//	/**
+//	 * MySQL 数据源配置
+//	 *
+//	 * @return DataSourceConfig
+//	 */
+//	private static DataSourceConfig oracleDataSourceConfig() {
+//		DataSourceConfig dataSourceConfig = new DataSourceConfig();
+//		dataSourceConfig.setDbType(DbType.ORACLE);
+//		dataSourceConfig.setTypeConvert(new MySqlTypeConvert());
+//		dataSourceConfig.setDriverName("oracle.jdbc.driver.OracleDriver");
+//		dataSourceConfig.setUrl(JDBC_URL);
+//		dataSourceConfig.setUsername(DB_USERNAME);
+//		dataSourceConfig.setPassword(DB_PASSWORD);
+//		return dataSourceConfig;
+//	}
+//
+//	/**
+//	 * 包相关配置信息
+//	 * <p>
+//	 * 配置生成代码的包信息,如生成的 Mapper 包,Service 包等
+//	 * </p>
+//	 */
+//	private static PackageConfig packageConfig() {
+//		PackageConfig packageConfig = new PackageConfig();
+//		// 设置父包
+//		packageConfig.setParent(PACKAGE);
+//		// TODO 设置生成代码的包
+//		// Controller 包
+//		packageConfig.setController("controller");
+//		// 数据库表映射对象包
+//		packageConfig.setEntity("entity");
+//		// Mapper 接口包,含 XML 文件
+//		packageConfig.setMapper("mapper");
+//		// Service 接口包
+//		packageConfig.setService("service");
+//		// Service 接口实现类包
+//		packageConfig.setServiceImpl("service.impl");
+//		return packageConfig;
+//	}
+//}
+//

+ 22 - 0
src/main/java/com/fdkankan/project/tieta/mapper/FullphotoFileindexMapper.java

@@ -0,0 +1,22 @@
+package com.fdkankan.project.tieta.mapper;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fdkankan.project.tieta.entity.FullphotoFileindex;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author dsx
+ * @since 2024-07-01
+ */
+public interface FullphotoFileindexMapper extends BaseMapper<FullphotoFileindex> {
+
+    Page<FullphotoFileindex> pageStationCodeAndEntityId(Page<FullphotoFileindex> page);
+
+}

+ 26 - 0
src/main/java/com/fdkankan/project/tieta/service/FullphotoFileindexService.java

@@ -0,0 +1,26 @@
+package com.fdkankan.project.tieta.service;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fdkankan.project.tieta.entity.FullphotoFileindex;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author dsx
+ * @since 2024-07-01
+ */
+public interface FullphotoFileindexService extends IService<FullphotoFileindex> {
+
+    List<FullphotoFileindex> listByStationCodeAndEntityId(String stationCode, String entityId);
+
+    Page<FullphotoFileindex> pageStationCodeAndEntityId(long current, int size);
+
+
+
+}

+ 6 - 0
src/main/java/com/fdkankan/project/tieta/service/IConvertService.java

@@ -1,10 +1,16 @@
 package com.fdkankan.project.tieta.service;
 
+import com.fdkankan.project.tieta.bean.ResultData;
+import com.fdkankan.project.tieta.dto.ScenePushDTO;
 import com.fdkankan.project.tieta.dto.SendConvertDTO;
 
 public interface IConvertService {
 
     void sendConvert(SendConvertDTO dto);
 
+    ResultData scenePush(ScenePushDTO dto);
+
+    void scenePushHistory();
+
 
 }

+ 71 - 2
src/main/java/com/fdkankan/project/tieta/service/impl/ConvertServiceImpl.java

@@ -1,21 +1,41 @@
 package com.fdkankan.project.tieta.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fdkankan.project.tieta.bean.ResultData;
 import com.fdkankan.project.tieta.constant.Constant;
+import com.fdkankan.project.tieta.constant.ServerCode;
+import com.fdkankan.project.tieta.dto.ScenePushDTO;
 import com.fdkankan.project.tieta.dto.SendConvertDTO;
+import com.fdkankan.project.tieta.entity.FullphotoFileindex;
+import com.fdkankan.project.tieta.service.FullphotoFileindexService;
 import com.fdkankan.project.tieta.service.IConvertService;
 import com.fdkankan.rabbitmq.util.RabbitMqProducer;
+import com.fdkankan.redis.util.RedisUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.log4j.spi.ErrorCode;
 import org.apache.tomcat.Jar;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Slf4j
 @Service
 public class ConvertServiceImpl implements IConvertService {
 
     @Autowired
     private RabbitMqProducer mqProducer;
-//    @Autowired
-//    private MqProducerUtils
+    @Autowired
+    private FullphotoFileindexService fullphotoFileindexService;
+    @Autowired
+    private RedisUtil redisUtil;
 
     @Override
     public void sendConvert(SendConvertDTO dto) {
@@ -24,4 +44,53 @@ public class ConvertServiceImpl implements IConvertService {
         playload.put("zipUrl", dto.getUrl());
         mqProducer.sendByWorkQueue(Constant.QUEUE_SCENE_CONVERT, playload);
     }
+
+    @Override
+    public ResultData scenePush(ScenePushDTO dto) {
+        JSONObject playload = new JSONObject();
+        playload.put("stationCode", dto.getStationCode());
+        playload.put("entityId", dto.getEntityId());
+        List<FullphotoFileindex> fullphotoFileindices = fullphotoFileindexService.listByStationCodeAndEntityId(dto.getStationCode(), dto.getEntityId());
+        if(CollUtil.isEmpty(fullphotoFileindices)){
+            return ResultData.error(ServerCode.RESOURCE_NOT_EXIST);
+        }
+        List<JSONObject> fileList = fullphotoFileindices.stream().map(v -> {
+            JSONObject item = new JSONObject();
+            item.put("fileName", v.getFileName());
+            item.put("fileType", v.getFileType());
+            item.put("fileUrl", v.getFileUrl());
+            return item;
+        }).collect(Collectors.toList());
+        playload.put("fileList", fileList);
+        mqProducer.sendByWorkQueue(Constant.QUEUE_SCENE_CONVERT + "-2", playload);
+        return ResultData.ok();
+    }
+
+    @Override
+    public void scenePushHistory() {
+        List<FullphotoFileindex> fullphotoFileindices = null;
+        long current = 1;
+        int size = 100;
+        Page<FullphotoFileindex> fullphotoFileindexPage = null;
+        do {
+            fullphotoFileindexPage = fullphotoFileindexService.pageStationCodeAndEntityId(current, size);
+            fullphotoFileindices = fullphotoFileindexPage.getRecords();
+            if(CollUtil.isNotEmpty(fullphotoFileindices)){
+                for (FullphotoFileindex item : fullphotoFileindices) {
+                    boolean doned = redisUtil.hHasKey(Constant.REDIS_SCENE_CONVERT_HISTORY, item.getStationCode() + "_" + item.getEntityId());
+                    if(!doned){
+                        try {
+                            this.scenePush(ScenePushDTO.builder().stationCode(item.getStationCode()).entityId(item.getEntityId()).build());
+                            Map<String, Object> map = new HashMap<>();
+                            map.put(item.getStationCode() + "_" + item.getEntityId(), "1");
+                            redisUtil.hmset(Constant.REDIS_SCENE_CONVERT_HISTORY, map);
+                        }catch (Exception e){
+                            log.error("history scene push fail, stationCode:{}, entityId:{}", item.getStationCode(), item.getEntityId(), e);
+                        }
+                    }
+                }
+            }
+            current++;
+        }while (fullphotoFileindexPage.hasNext());
+    }
 }

+ 39 - 0
src/main/java/com/fdkankan/project/tieta/service/impl/FullphotoFileindexServiceImpl.java

@@ -0,0 +1,39 @@
+package com.fdkankan.project.tieta.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fdkankan.project.tieta.entity.FullphotoFileindex;
+import com.fdkankan.project.tieta.mapper.FullphotoFileindexMapper;
+import com.fdkankan.project.tieta.service.FullphotoFileindexService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author dsx
+ * @since 2024-07-01
+ */
+@Service
+public class FullphotoFileindexServiceImpl extends ServiceImpl<FullphotoFileindexMapper, FullphotoFileindex> implements FullphotoFileindexService {
+
+    @Override
+    public List<FullphotoFileindex> listByStationCodeAndEntityId(String stationCode, String entityId) {
+        return this.list(new LambdaQueryWrapper<FullphotoFileindex>()
+                .eq(FullphotoFileindex::getStationCode, stationCode)
+                .eq(FullphotoFileindex::getEntityId, entityId)
+                .eq(FullphotoFileindex::getStatus, 1)
+                .orderByAsc(FullphotoFileindex::getUpTime));
+    }
+
+    @Override
+    public Page<FullphotoFileindex> pageStationCodeAndEntityId(long current, int size) {
+        Page<FullphotoFileindex> fullphotoFileindexPage = new Page<>(current, size);
+        Page<FullphotoFileindex> fullphotoFileindexPage1 = this.baseMapper.pageStationCodeAndEntityId(fullphotoFileindexPage);
+        return fullphotoFileindexPage1;
+    }
+}

+ 113 - 0
src/main/java/com/fdkankan/project/tieta/utils/FdfsUtil.java

@@ -0,0 +1,113 @@
+package com.fdkankan.project.tieta.utils;
+
+import cn.hutool.core.lang.UUID;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import com.alibaba.fastjson.JSON;
+import com.fdkankan.project.tieta.bean.TietaResBean;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+@Slf4j
+public class FdfsUtil {
+
+    @Value("${fdfs.address}")
+    private String address;
+
+    @Value("${fdfs.api.getSignature}")
+    private String api_getSignature;
+
+    @Value("${fdfs.api.uploadFile}")
+    private String api_uploadFile;
+
+    @Value("${fdfs.sysCode}")
+    private String sysCode;
+
+    public String getSignature(String nonce, String timestamp){
+        Map<String, String> headers = new HashMap<>();
+        headers.put("timestamp", timestamp);
+        headers.put("nonce", nonce);
+        headers.put("sysCode", sysCode);
+        HttpRequest httpRequest = HttpRequest.post(address.concat(api_getSignature)).addHeaders(headers).timeout(5000);
+        HttpResponse res = httpRequest.execute();
+        String resBody = res.body();
+        res.close();
+        TietaResBean<String> tietaResBean = JSON.parseObject(resBody, TietaResBean.class);
+        String code = tietaResBean.getCode();
+        if(!"000000".equals(code)){
+            throw new RuntimeException("获取签名失败, code:" + code);
+        }
+        return tietaResBean.getData();
+    }
+
+    public Map<String, String> uploadFile(String nonce, String timestamp, String signature, String filePath){
+
+        Map<String, String> headers = new HashMap<>();
+        headers.put("timestamp", timestamp);
+        headers.put("nonce", nonce);
+        headers.put("sysCode", sysCode);
+        headers.put("signature", signature);
+
+        Map<String, Object> test = new HashMap<>();
+        test.put("visibilityLevel", "1003");
+        test.put("file", new File(filePath));
+        test.put("userId", "111111");
+        HttpRequest httpRequest = HttpRequest.post(address.concat(api_uploadFile)).form(test).addHeaders(headers).timeout(60000);
+        HttpResponse res = httpRequest.execute();
+        String resBody = res.body();
+        log.info("upload file response : {}", resBody);
+        res.close();
+        TietaResBean<Map<String, String>> tietaResBean = JSON.parseObject(resBody, TietaResBean.class);
+        String code = tietaResBean.getCode();
+        if(!"000000".equals(code)){
+            throw new RuntimeException("上传文件失败, code:" + code);
+        }
+        return tietaResBean.getData();
+    }
+
+    public Map<String, String> uploadFile(String filePath){
+        String nonce = UUID.fastUUID().toString();
+        String timestamp = String.valueOf(new Date().getTime());
+        String signature = getSignature(nonce, timestamp);
+        return uploadFile(nonce, timestamp, signature, filePath);
+    }
+
+    public static void main(String[] args) {
+        Map<String, String> headers = new HashMap<>();
+        headers.put("timestamp", "1719389524320");
+        headers.put("nonce", "123123");
+        headers.put("sysCode", "CT00017");
+        headers.put("signature", "3044022062501c9896a919d81d00216379a84c7d89b2d7315a22f89aee2ce7c1185f656c02206d4694fb685247a289e1c0d11e7492311ef66354c64cd2234fa593e02a635074");
+
+        Map<String, Object> test = new HashMap<>();
+        test.put("visibilityLevel", "1003");
+        test.put("file", new File("D:\\四维时代\\中国铁塔\\数据推送示例\\KK-R4YYV4yIZlT\\images\\4k\\ff54999789b970e64e2845a2337954f9.jpg"));
+        test.put("userId", "111111");
+        HttpRequest httpRequest = HttpRequest.post("http://10.180.22.41:8761/ChinatowerFileService/uploadFile/").form(test).addHeaders(headers).timeout(60000);
+        HttpResponse res = httpRequest.execute();
+        String resBody = res.body();
+        res.close();
+        TietaResBean<Map<String, String>> tietaResBean = JSON.parseObject(resBody, TietaResBean.class);
+        String code = tietaResBean.getCode();
+        if(!"000000".equals(code)){
+            throw new RuntimeException("上传文件失败, code:" + code);
+        }
+        Map<String, String> data = tietaResBean.getData();
+        System.out.println(data);
+    }
+
+
+
+
+
+
+
+
+}

+ 40 - 0
src/main/java/com/fdkankan/rabbitmq/callback/ProducerCallback.java

@@ -0,0 +1,40 @@
+package com.fdkankan.rabbitmq.callback;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.connection.CorrelationData;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.stereotype.Component;
+
+/**
+ * <p>
+ * TODO
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/4/19
+ **/
+@Slf4j
+@Component
+public class ProducerCallback implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnCallback {
+
+    //confirms模式:无论exchange投递消息是成功或是失败,都会返回ack,我们可以根据返回的ack是成功还是失败,做相应的业务处理
+    @Override
+    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
+        String messageId = correlationData.getId();
+        //投递成功
+        if(ack){
+            log.info("消息投递成功,id:{}", messageId);
+            return;
+        }
+        //投递失败
+        log.error("消息投递失败,id:{},失败原因:{}", messageId, cause);
+    }
+
+    //return模式:只有exchange投递消息失败时,才会执行回调函数,来做一些相应的业务处理
+    @Override
+    public void returnedMessage(Message returnedMessage, int replyCode, String replyText, String exchange, String routingKey) {
+        log.info("消息从Exchange路由到Queue失败: exchange: {}, route: {}, replyCode: {}, replyText: {}, message: {}", exchange, routingKey, replyCode, replyText, returnedMessage);
+
+    }
+}

+ 119 - 0
src/main/java/com/fdkankan/rabbitmq/config/RabbitMqConfig.java

@@ -0,0 +1,119 @@
+package com.fdkankan.rabbitmq.config;
+
+import com.fdkankan.rabbitmq.callback.ProducerCallback;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.Resource;
+
+@Configuration
+@Slf4j
+public class RabbitMqConfig {
+
+//    @Resource
+//    private QueueConfig queueConfig;
+//    @Resource
+//    private ExchangeConfig exchangeConfig;
+    /**
+     * 连接工厂
+     */
+    @Resource
+    private ConnectionFactory connectionFactory;
+
+    @Resource
+    private ProducerCallback producerCallback;
+
+    /**
+     * 指定序列化转换器,否则mq消息存进去
+     * @return
+     */
+    @Bean
+    public Jackson2JsonMessageConverter messageConverter(){
+        return new Jackson2JsonMessageConverter();
+    }
+
+
+    /**
+     * 将消息队列和交换机进行绑定,指定路由
+     */
+//    @Bean
+//    public Binding bindingDirect() {
+//        return BindingBuilder.bind(queueConfig.easyQueue()).to(exchangeConfig.directExchange()).with(RabbitMQConstant.ROUTING_KEY_EASY);
+//    }
+//
+//    @Bean
+//    public Binding bindingWork() {
+//        return BindingBuilder.bind(queueConfig.workQueue()).to(exchangeConfig.workExchange()).with(RabbitMQConstant.ROUTING_KEY_WORK);
+//    }
+//
+//    @Bean
+//    public Binding bindingTopic() {
+//        return BindingBuilder.bind(queueConfig.topicQueue()).to(exchangeConfig.topicExchange()).with(RabbitMQConstant.ROUTING_KEY_TOPIC_FIRST);
+//    }
+//
+//    @Bean
+//    public Binding bindingTopicSecond() {
+//        return BindingBuilder.bind(queueConfig.topicQueueSecond()).to(exchangeConfig.topicExchange()).with(RabbitMQConstant.ROUTING_KEY_TOPIC_SECOND);
+//    }
+//
+//    @Bean
+//    public Binding bindingFanout() {
+//        return BindingBuilder.bind(queueConfig.fanoutQueue()).to(exchangeConfig.fanoutExchange());
+//    }
+//
+//    @Bean
+//    public Binding bindingFanoutSecond() {
+//        return BindingBuilder.bind(queueConfig.fanoutQueueSecond()).to(exchangeConfig.fanoutExchange());
+//    }
+
+    /** ======================== 定制一些处理策略 =============================*/
+
+    /**
+     * 定制化amqp模版
+     * <p>
+     * Rabbit MQ的消息确认有两种。
+     * <p>
+     * 一种是消息发送确认:这种是用来确认生产者将消息发送给交换机,交换机传递给队列过程中,消息是否成功投递。
+     * 发送确认分两步:一是确认是否到达交换机,二是确认是否到达队列
+     * <p>
+     * 第二种是消费接收确认:这种是确认消费者是否成功消费了队列中的消息。
+     */
+    @Bean
+    public RabbitTemplate rabbitTemplate(Jackson2JsonMessageConverter messageConverter) {
+        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
+
+        rabbitTemplate.setMessageConverter(messageConverter);
+
+        // 消息发送失败返回到队列中, yml需要配置 publisher-returns: true
+//        rabbitTemplate.setMandatory(true);
+
+        /**
+         * 使用该功能需要开启消息确认,yml需要配置 publisher-confirm-type: correlated:表示消息成功到达Broker后触发ConfirmCalllBack回调
+         * 通过实现ConfirmCallBack接口,用于实现消息发送到交换机Exchange后接收ack回调
+         * correlationData  消息唯一标志
+         * ack              确认结果
+         *
+         * cause            失败原因
+         */
+        rabbitTemplate.setConfirmCallback(producerCallback);
+
+        /**
+         * 使用该功能需要开启消息返回确认,yml需要配置 publisher-returns: true
+         * 通过实现ReturnCallback接口,如果消息从交换机发送到对应队列失败时触发
+         * message    消息主体 message
+         * replyCode  消息主体 message
+         * replyText  描述
+         * exchange   消息使用的交换机
+         * routingKey 消息使用的路由键
+         */
+//        rabbitTemplate.setReturnCallback(new ProducerCallback());
+
+
+        return rabbitTemplate;
+    }
+
+}

+ 112 - 0
src/main/java/com/fdkankan/rabbitmq/util/RabbitMqProducer.java

@@ -0,0 +1,112 @@
+package com.fdkankan.rabbitmq.util;
+
+import cn.hutool.json.JSONObject;
+import com.rabbitmq.client.AMQP.Queue.DeclareOk;
+import com.rabbitmq.client.Channel;
+import lombok.Data;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.amqp.rabbit.connection.CorrelationData;
+import org.springframework.amqp.rabbit.core.ChannelCallback;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.UUID;
+
+/**
+ * <p>
+ * TODO
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/4/19
+ **/
+@Component
+@Data
+public class RabbitMqProducer {
+
+    private Logger log = LoggerFactory.getLogger(this.getClass().getName());
+
+//    @Autowired
+//    ModelingQueueConfig modelingQueueConfig;
+
+    @Autowired
+    private RabbitTemplate rabbitTemplate;
+
+    /**
+     * 工作队列模式发送消息
+     * @param queue 队列名
+     * @param content 载荷
+     */
+    public void sendByWorkQueue(String queue, Object content){
+        String messageId = UUID.randomUUID().toString();
+        log.info("开始发送Mq消息,messageId:{},消息队列:{},消息内容:{}",messageId, queue, new JSONObject(content).toString());
+        rabbitTemplate.convertAndSend(queue, content, message -> {
+            message.getMessageProperties().setMessageId(messageId);
+            return message;
+        }, new CorrelationData(messageId));
+    }
+    /**
+     * 工作队列模式发送消息
+     * @param exchange 交换机
+     * @param queue 队列名
+     * @param content 载荷
+     */
+    public void sendByWorkQueue(String exchange,String queue, Object content){
+        String messageId = UUID.randomUUID().toString();
+        log.info("开始发送Mq消息,messageId:{},消息队列:{},消息内容:{}",messageId, queue, new JSONObject(content).toString());
+        rabbitTemplate.convertAndSend(exchange,queue, content, message -> {
+            message.getMessageProperties().setMessageId(messageId);
+            return message;
+        }, new CorrelationData(messageId));
+    }
+    /**
+     * 工作队列模式发送带优先级消息
+     * @param queue 队列名
+     * @param content 载荷
+     * @param priority 优先级,正整数,值越大优先级越高,当值大于队列设置的最大优先级时,效果等同于最大优先级
+     */
+    public void sendByWorkQueue(String queue, Object content, Integer priority){
+        String messageId = UUID.randomUUID().toString();
+        log.info("开始发送Mq消息,messageId:{},消息队列:{},消息内容:{}",messageId, queue, new JSONObject(content).toString());
+        rabbitTemplate.convertAndSend(queue, content, message -> {
+            message.getMessageProperties().setMessageId(messageId);
+            message.getMessageProperties().setPriority(priority);
+            return message;
+        }, new CorrelationData(messageId));
+    }
+
+    /**
+     * 获取队列未被消费的消息数量
+     * @return
+     */
+    public int getMessageCount(String queueName) {
+        DeclareOk declareOk = rabbitTemplate.execute(new ChannelCallback<DeclareOk>() {
+            public DeclareOk doInRabbit(Channel channel) throws Exception {
+                return channel.queueDeclarePassive(queueName);
+            }
+        });
+
+        return declareOk.getMessageCount();
+    }
+
+    /**
+     * 工作队列模式发送消息到多个队列
+     * @param queue 队列名
+     * @param content 载荷
+     */
+    public void sendByWorkToQueues(Object content, String... queues){
+        for (String queue : queues) {
+            String messageId = UUID.randomUUID().toString();
+            log.info("开始发送Mq消息,messageId:{},消息队列:{},消息内容:{}",messageId, queue, new JSONObject(content).toString());
+            rabbitTemplate.convertAndSend(queue, content, message -> {
+                message.getMessageProperties().setMessageId(messageId);
+                return message;
+            }, new CorrelationData(messageId));
+        }
+    }
+
+
+
+}

+ 44 - 0
src/main/java/com/fdkankan/redis/config/RedisConfig.java

@@ -0,0 +1,44 @@
+package com.fdkankan.redis.config;
+
+
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+@Configuration
+@AutoConfigureAfter(RedisAutoConfiguration.class)
+public class RedisConfig {
+
+    @Bean
+    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
+        RedisTemplate template = new RedisTemplate();
+        template.setConnectionFactory(redisConnectionFactory);
+        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
+
+        template.setKeySerializer(stringRedisSerializer);
+        template.setValueSerializer(stringRedisSerializer);
+        template.setHashKeySerializer(stringRedisSerializer);
+        template.setHashValueSerializer(stringRedisSerializer);
+
+        template.afterPropertiesSet();
+        return template;
+    }
+
+    /**
+     * 由于v4场景中心要获取v3的登录用户信息,而v3的jedis使用的是默认的jdk序列化器,所以这里提供了一个特殊的redistemplate,v3废弃后需要删除
+     * @param redisConnectionFactory
+     * @return
+     */
+    @Bean
+    public RedisTemplate<String, Object> redisTemplate2(RedisConnectionFactory redisConnectionFactory) {
+        RedisTemplate template = new RedisTemplate();
+        template.setConnectionFactory(redisConnectionFactory);
+        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
+        template.setKeySerializer(stringRedisSerializer);
+        return template;
+    }
+}

+ 225 - 0
src/main/java/com/fdkankan/redis/constant/RedisKey.java

@@ -0,0 +1,225 @@
+package com.fdkankan.redis.constant;
+
+public class RedisKey {
+    /**
+     * 过期时间:1分钟
+     */
+    public static final int EXPIRE_TIME_1_MINUTE = 60;
+
+    /**
+     * 过期时间:5分钟
+     */
+    public static final int EXPIRE_TIME_5_MINUTE = 5*60;
+
+    /**
+     * 过期时间:10分钟
+     */
+    public static final int EXPIRE_TIME_10_MINUTE = 10*60;
+
+    /**
+     * 过期时间:30分钟
+     */
+    public static final int EXPIRE_TIME_30_MINUTE = 30*60;
+
+    /**
+     * 过期时间:2小时
+     */
+    public static final int EXPIRE_TIME_2_HOUR = 2*60*60;
+
+    /**
+     * 用户过期时间
+     */
+    public static final int USER_EXPIRE_TIME = 6*60*60;
+
+    /**
+     * 相机登陆7天有效期
+     */
+    public static final int CAMERA_EXPIRE_7_TIME = 7*24*60*60;
+
+    public static final String SYSTEM_PREFIX = "4dkankan";
+
+    /**
+     * 登录token
+     */
+    public static String TOKEN_USER = "token:type:%s:name:%s";
+
+    /**
+     * ssouser key
+     */
+    public static String SSO_USER = "sso_user:name:%s";
+    /**
+     * 开发者信息
+     */
+    public static String TM_DEVELOPER = "developer:appid:%s";
+
+    /**
+     * 场景浏览量
+     */
+    public static String SCENE_VISIT_CNT = "scene:visit:cnt";
+
+
+    /**
+     * 场景码池
+     */
+    public static String FDKANKAN_SCENE_NUMS = "4dkankan:scene:nums";
+
+
+    public static final String SCENE_BUILDING = SYSTEM_PREFIX+":scene:building:%s";
+
+    /**
+     * 场景下载进度
+     */
+    // TODO: 2022/3/29  这个是V3版本使用的key,V4版本稳定后,这个要删除
+    public static final String PREFIX_DOWNLOAD_PROGRESS="downloads:progress:%s";
+
+    /**
+     * 场景下载进度
+     */
+    public static final String PREFIX_DOWNLOAD_PROGRESS_V4="downloads:progress:v4:%s";
+
+    /**
+     * 即将要下载场景的场景码列表
+     */
+    public static final String DOWNLOAD_TASK="downloads:task";
+
+    /**
+     * 正在下载的场景码列表
+     */
+    public static final String SCENE_DOWNLOAD_ING="scene:downloads:ing";
+
+    /**
+     * 正在下载的场景码列表
+     */
+    public static final String SCENE_V3_DOWNLOAD_ING="scene:v3:downloads:ing";
+
+    /**
+     * scenejson缓存
+     */
+    public static final String SCENE_JSON = "scenejson:num:%s";
+
+    /**
+     * 场景热点hash列表
+     */
+    public static final String SCENE_HOT_DATA = "scene:hotdata:num:%s";
+
+    /**
+     * 热点icons数据列表
+     */
+    public static final String SCENE_HOT_ICONS = "scene:hoticons:num:%s";
+
+    /**
+     * 场景关联数据列表
+     */
+    public static final String SCENE_LINKPAN_DATA = "scene:LinkPan:num:%s";
+
+    /**
+     * 场景关联styles数据列表
+     */
+    public static final String SCENE_LINKPAN_STYLES = "scene:LinkPanStyles:num:%s";
+
+    /**
+     * 场景关联styles数据列表
+     */
+    public static final String SCENE_BILLBOARDS_STYLES = "scene:billboardsStyles:num:%s";
+
+    /**
+     * 场景指示牌数据列表
+     */
+    public static final String SCENE_BILLBOARDS = "scene:billboards:num:%s";
+
+    public static final String SCENE_CUT_MODEL = "scene:cutmodel:num:%s";
+
+    /**
+     * 场景下载任务列表
+     */
+    public static final String SCENE_DOWNLOADS_TASK_V4 = "scene:downloads:task:v4";
+
+    /**
+     * 场景升级进度
+     */
+    public static final String scene_upgrade_progress_num = "scene:upgrade:progress:num:%s";
+
+    /**
+     * v3版本user类型token
+     */
+    public static final String TOKEN_V3 = "token#%s";
+
+    /**
+     * user类型token
+     */
+    public static final String USER_TOKEN_KEY = "token#%s";
+
+    /**
+     * 场景协作管理
+     */
+    public static final String SCENE_COOPERATION_NUM_USERID = "scene:cooperation:num:userId";
+
+
+    /**
+     * 管理后台key
+     */
+    public static final String  MANAGE_MENU ="manage_menu";
+    public static final String  MANAGE_PERM_USER ="manage_perm_user:%s";
+    public static final String  MANAGE_ROLE_USER ="manage_role_user:%s";
+
+    /**
+     * 马赛克列表
+     */
+    public static final String SCENE_MOSAIC_DATA = "scene:mosaic:num:%s";
+
+    /**
+     * 滤镜列表
+     */
+    public static final String SCENE_filter_DATA = "scene:filter:num:%s";
+
+    /**
+     * 场景资源清理,查询场景limit下标
+     */
+    public static final String SCENE_CLEAN_INDEX = "scene:clean:index";
+
+    /**
+     * 上传matterprodata状态
+     */
+    public static final String SCENE_UPLOAD_MATTERPRO_NUM= "scene:upload:matterpro:num";
+
+    /**
+     * 人体抠图任务id
+     */
+    public static final String SCENE_BODY_SEGMENT= "scene:body:segment:uuid:%s";
+
+    /**
+     * 场景oss原始资源目录删除
+     */
+    public static final String SCENE_OSS_HOME_DIR_DELETE= "scene:oss:home:dir:delete:unicode:%s";
+
+    /**
+     * 场景oss原始资源目录上传
+     */
+    public static final String SCENE_OSS_HOME_DIR_UPLOAD= "scene:oss:home:dir:upload:unicode:%s";
+
+    /**
+     * 场景oss原始资源目录上传
+     */
+    public static final String SCENE_BUILD_EXPECT_TOTAL_TIME_NUM= "scene:build:expect:total:time:num:%s";
+
+    /**
+     * 场景oss原始资源目录上传
+     */
+    public static final String SCENE_BUILD_FINISH_NUM = "scene:build:finish:num:%s";
+
+    /**
+     * 场景oss原始资源目录上传
+     */
+    public static final String SINGLE_MODELING_SERVER_BUSY = "singleModelingServerBusy";
+
+    /**
+     * 打点系统应用id缓存
+     */
+    public static final String TRACK_APPID = "track:appid";
+
+    public static final String SCENE_DRAW = "scene:draw:num:%s";
+
+
+
+
+}

+ 192 - 0
src/main/java/com/fdkankan/redis/constant/RedisLockKey.java

@@ -0,0 +1,192 @@
+package com.fdkankan.redis.constant;
+
+import cn.hutool.core.io.FileUtil;
+
+import java.io.File;
+
+/**
+ * <p>
+ *   分布式锁key定义
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/1/12
+ **/
+public class RedisLockKey {
+
+    /**
+     * 场景浏览量
+     */
+    public static String LOCK_SCENE_VISIT_CNT = "lock:scene:visit:cnt:scenecode:%s";
+
+    /**
+     * 场景访问量更新锁 hash
+     */
+    public static String LOCK_SCENE_VISIT_UPDATE = "lock:scene:visit:update";
+
+    /**
+     *
+     *
+     *
+     * 场景上传图片锁
+     */
+    public static String LOCK_UPLOAD_PIC = "lock:upload:pic:scenecode:%s";
+
+    /**
+     * 场景pro上传图片锁
+     */
+    public static String LOCK_UPLOAD_PRO_PIC = "lock:upload:pro:pic:scenecode:%s";
+
+    /**
+     * 场景上传音频锁
+     */
+    public static String LOCK_UPLOAD_VOICE = "lock:upload:voice:scenecode:%s";
+
+    /**
+     * 场景pro上传音频锁
+     */
+    public static String LOCK_UPLOAD_PRO_VOICE = "lock:upload:pro:voice:scenecode:%s";
+
+    /**
+     * 画墙重建模型锁
+     */
+    public static String LOCK_UPLOAD_FLOORJSON_REBUILD = "lock:upload:floorjson:rebuild:scenecode:%s";
+
+    /**
+     * 上传图片多媒体数据锁
+     */
+    public static String LOCK_UPLOAD_FLOORPLAN_PNG = "lock:upload:floorplan:png:scenecode:%s";
+
+    /**
+     * 加载场景码池锁
+     */
+    public static String LOCK_FDKANKAN_SCENE_NUMS = "lock:4dkankan:scene:nums";
+
+    /**
+     * 同步场景
+     */
+    public static String LOCK_SCENE_SYNC = "lock:scene:sync:num:%s";
+
+    /**
+     * 热点数据恢复锁
+     */
+    public static String LOCK_HOT_DATA_SYNC = "lock:hot:data:sync:num:%s";
+
+    /**
+     * icons数据恢复锁
+     */
+    public static String LOCK_HOT_ICONS_SYNC = "lock:hot:icons:sync:num:%s";
+
+    /**
+     * 场景关联数据恢复锁
+     */
+    public static String LOCK_LINKPAN_DATA_SYNC = "lock:linkpan:data:sync:num:%s";
+
+    /**
+     * 场景关联styles数据恢复锁
+     */
+    public static String LOCK_LINKPAN_STYLES_SYNC = "lock:linkpan:styles:sync:num:%s";
+
+    /**
+     * 场景关联styles数据恢复锁
+     */
+    public static String LOCK_BILLBOARDS_STYLES_SYNC = "lock:Billboards:styles:sync:num:%s";
+
+    /**
+     * 场景指示牌数据恢复锁
+     */
+    public static String LOCK_BILLBOARDS_SYNC = "lock:billboards:sync:num:%s";
+
+    /**
+     * 裁剪模型数据恢复锁
+     */
+    public static String LOCK_CUT_MODEL_SYNC = "lock:cutmodel:sync:num:%s";
+
+    /**
+     * 热点数据写文件锁
+     */
+    public static String LOCK_HOT_JSON = "lock:hot:json:num:%s";
+
+    /**
+     * 批量生成场景码锁
+     */
+    public static String LOCK_BATCH_CREATE_NUM = "lock:batch:create:num";
+
+    /**
+     * 加载场景中断下载列表锁
+     */
+    public static String LOCK_SCENE_DOWNLOAD_ING = "lock:scene:downloads:ing";
+
+
+    /**
+     * 加载场景中断下载列表锁
+     */
+    public static String LOCK_STARTUP_MODELING_SERVER = "lock:startup:modeling:server";
+
+    /**
+     * 加载场景中断下载列表锁
+     */
+    public static String LOCK_SCENE_UPGRADE_V4 = "lock:scene:upgrade:v4:num:%s";
+
+    /**
+     * 场景关联数据写本地文件锁
+     */
+    public static String LOCK_LINK_SCENE_JSON = "lock:link:scene:json:num:%s";
+
+    /**
+     * 场景关联数据写本地文件锁
+     */
+    public static String LOCK_SCENE_UPGRADE_FAILED_ROLLBACK = "lock:scene:upgrade:failed:rollback";
+
+    /**
+     * 马赛克数据恢复锁
+     */
+    public static String LOCK_MOSAIC_DATA_SYNC = "lock:mosaic:data:sync:num:%s";
+
+    /**
+     * 马赛克数据写文件锁
+     */
+    public static String LOCK_MOSAIC_JSON = "lock:mosaic:json:num:%s";
+
+    /**
+     * 滤镜数据写文件锁
+     */
+    public static String LOCK_filter_JSON = "lock:filter:json:num:%s";
+
+    /**
+     * 滤镜数据恢复锁
+     */
+    public static String LOCK_FILTER_DATA_SYNC = "lock:filter:data:sync:num:%s";
+
+    /**
+     * 场景资源清理定时任务锁
+     */
+    public static final String LOCK_SCENE_CLEAN = "lock:scene:clean";
+
+    /**
+     * 思维打包下载锁
+     */
+    public static final String LOCK_DOWNLOAD_SIWEI_HTML = "lock:download:siwei:html";
+
+    /**
+     * 思维打包下载锁
+     */
+    public static final String LOCK_GET_MATTERPRO_NUM = "lock:get:matterpro:num";
+
+    public static final String LOCK_CLEAN_SCENE_ORIG_V3 = "lock:clean:scene:orig:v3";
+
+    public static final String LOCK_CLEAN_SCENE_ORIG_V4 = "lock:clean:scene:orig:v4";
+
+    public static final String LOCK_CLEAN_SCENE_DELETED_ORIG_V3 = "lock:clean:scene:deleted:orig:v3";
+
+    public static final String LOCK_CLEAN_SCENE_DELETED_ORIG_V4 = "lock:clean:scene:deleted:orig:v4";
+
+    public static String LOCK_SCENE_DRAW = "lock:sceneDraw:sync:num:%s";
+
+    public static void main(String[] args) {
+        FileUtil.copyContent(new File("F:\\test\\test"), new File("F:\\test\\test2"), true);
+    }
+
+
+
+}

+ 145 - 0
src/main/java/com/fdkankan/redis/util/RedisLockUtil.java

@@ -0,0 +1,145 @@
+package com.fdkankan.redis.util;
+
+import cn.hutool.core.lang.UUID;
+import cn.hutool.core.util.StrUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.script.DefaultRedisScript;
+import org.springframework.stereotype.Component;
+
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+
+@Component
+@Slf4j
+public class RedisLockUtil {
+
+    private ConcurrentHashMap<String, String> THREADID_LOCKVAL_MAP = new ConcurrentHashMap<>();
+
+    @Autowired
+    private RedisTemplate redisTemplate;
+
+    private static final String UNLOCK_LUA =
+            "if redis.call('get',KEYS[1]) == ARGV[1] then\n" +
+            "    return redis.call('del',KEYS[1])\n" +
+            "else\n" +
+            "    return 0\n" +
+            "end";
+
+    /**
+     * 加锁,自旋重试三次
+     * 默认以线程id作为锁的值
+     *
+     * @param lockKey 锁key
+     * @param expireTime 锁过期时间 单位 毫秒
+     * @return
+     */
+    public boolean lock(String lockKey, int expireTime) {
+        return this.lock(lockKey, null, expireTime);
+    }
+
+    /**
+     * 加锁,自旋重试三次
+     * @param lockKey 锁key
+     * @param lockVal 锁value
+     * @param expireTime 锁过期时间 单位 毫秒
+     * @return
+     */
+    public boolean lock(String lockKey, String lockVal, int expireTime) {
+        boolean locked = false;
+        int tryCount = 3;
+        String threadId = null;
+        String uuid = null;
+        if(lockVal == null){
+            threadId = String.valueOf(Thread.currentThread().getId());
+            uuid = UUID.randomUUID().toString();
+            lockVal = uuid + ":" + threadId;
+            log.info("加锁lockval:{}",lockVal);
+        }
+        while (tryCount > 0) {
+            locked = redisTemplate.opsForValue().setIfAbsent(lockKey, lockVal, expireTime, TimeUnit.SECONDS);
+            if(locked){
+                if(threadId != null){
+                    THREADID_LOCKVAL_MAP.put(threadId, lockVal);
+                }
+                return locked;
+            }
+            tryCount--;
+            try {
+                Thread.sleep(300);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+        return locked;
+    }
+
+    /**
+     * 非原子解锁,可能解别人锁,不安全
+     *
+     * @return
+     */
+    public boolean unlock(String lockKey) {
+        return this.unlock(lockKey, null);
+    }
+
+    /**
+     * 非原子解锁,可能解别人锁,不安全
+     *
+     * @return
+     */
+    public boolean unlock(String lockKey, String lockVal) {
+        if(lockVal == null){
+            String threadId = String.valueOf(Thread.currentThread().getId());
+            lockVal = THREADID_LOCKVAL_MAP.get(threadId);
+        }
+        if (StrUtil.isEmpty(lockKey) || Objects.isNull(lockVal))
+            return false;
+        boolean releaseLock = false;
+        String val = (String) redisTemplate.opsForValue().get(lockKey);
+        if (lockVal.equals(val)) {
+            releaseLock = redisTemplate.delete(lockKey);
+        }
+        return releaseLock;
+    }
+
+    /**
+     * 使用lua脚本解锁,不会解除别人锁
+     *
+     * @param
+     * @return
+     */
+    public boolean unlockLua(String lockKey) {
+        return this.unlockLua(lockKey, null);
+    }
+
+    /**
+     * 使用lua脚本解锁,不会解除别人锁
+     *
+     * @param
+     * @return
+     */
+    public boolean unlockLua(String lockKey, String lockVal) {
+        if(lockVal == null){
+            String threadId = String.valueOf(Thread.currentThread().getId());
+            lockVal = THREADID_LOCKVAL_MAP.get(threadId);
+        }
+        log.info("解锁lockval:{}",lockVal);
+        if (StrUtil.isEmpty(lockKey) || Objects.isNull(lockVal))
+            return false;
+        DefaultRedisScript<Long> redisScript = new DefaultRedisScript();
+        redisScript.setScriptText(UNLOCK_LUA);
+        redisScript.setResultType(Long.class);
+
+        Object result = redisTemplate.execute(redisScript, Arrays.asList(lockKey), lockVal);
+        return result.equals(Long.valueOf(1));
+    }
+
+
+
+
+
+}

+ 498 - 0
src/main/java/com/fdkankan/redis/util/RedisUtil.java

@@ -0,0 +1,498 @@
+package com.fdkankan.redis.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import java.time.Duration;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+@Component
+@Slf4j
+public class RedisUtil<K, V>{
+
+    @Autowired
+    private RedisTemplate redisTemplate;
+
+    /**
+     * 指定缓存失效时间
+     *
+     * @param key  键
+     * @param time 时间(秒)
+     * @return
+     */
+    public boolean expire(String key, long time) {
+        if (time > 0) {
+            redisTemplate.expire(key, time, TimeUnit.SECONDS);
+        }
+        return true;
+    }
+    /**
+     * 根据key 获取过期时间
+     *
+     * @param key 键 不能为null
+     * @return 时间(秒) 返回0代表为永久有效
+     */
+    public long getExpire(String key) {
+        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
+    }
+    /**
+     * 判断key是否存在
+     *
+     * @param key 键
+     * @return true 存在 false不存在
+     */
+    public boolean hasKey(String key) {
+        return redisTemplate.hasKey(key);
+    }
+    /**
+     * 删除缓存
+     *
+     * @param key 可以传一个值 或多个
+     */
+    @SuppressWarnings("unchecked")
+    public void del(String... key) {
+        if (key != null && key.length > 0) {
+            if (key.length == 1) {
+                redisTemplate.delete(key[0]);
+            } else {
+                redisTemplate.delete(CollectionUtils.arrayToList(key));
+            }
+        }
+    }
+    // ============================String=============================
+    /**
+     * 普通缓存获取
+     *
+     * @param key 键
+     * @return 值
+     */
+    public String get(String key) {
+        return key == null ? null : (String) redisTemplate.opsForValue().get(key);
+    }
+    /**
+     * 普通缓存放入
+     *
+     * @param key   键
+     * @param value 值
+     * @return true成功 false失败
+     */
+    public boolean set(String key, String value) {
+        redisTemplate.opsForValue().set(key, value);
+        return true;
+    }
+    /**
+     * 普通缓存放入并设置时间
+     *
+     * @param key   键
+     * @param value 值
+     * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
+     * @return true成功 false 失败
+     */
+    public boolean set(String key, String value, long time) {
+        if (time > 0) {
+            redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
+        } else {
+            set(key, value);
+        }
+        return true;
+    }
+    /**
+     * 递增
+     *
+     * @param key   键
+     * @param delta 要增加几(大于0)
+     * @return
+     */
+    public long incr(String key, long delta) {
+        if (delta < 0) {
+            throw new RuntimeException("递增因子必须大于0");
+        }
+        return redisTemplate.opsForValue().increment(key, delta);
+    }
+    /**
+     * 递减
+     *
+     * @param key   键
+     * @param delta 要减少几(小于0)
+     * @return
+     */
+    public long decr(String key, long delta) {
+        if (delta < 0) {
+            throw new RuntimeException("递减因子必须大于0");
+        }
+        return redisTemplate.opsForValue().increment(key, -delta);
+    }
+    // ================================Map=================================
+    /**
+     * HashGet
+     *
+     * @param key  键 不能为null
+     * @param item 项 不能为null
+     * @return 值
+     */
+    public String hget(String key, String item) {
+        return (String)redisTemplate.opsForHash().get(key, item);
+    }
+
+    /**
+     * HashGet
+     *
+     * @param key  键 不能为null
+     * @return 值
+     */
+    public List<String> hgetValues(String key) {
+        return redisTemplate.opsForHash().values(key);
+    }
+    /**
+     * 获取hashKey对应的所有键值
+     *
+     * @param key 键
+     * @return 对应的多个键值
+     */
+    public Map<String, String> hmget(String key) {
+        return redisTemplate.opsForHash().entries(key);
+    }
+
+
+    /**
+     * <p>
+            查询指定key中匹配多项
+     * </p>
+     * @author dengsixing
+     * @date 2022/2/8
+     * @param key
+     * @param items
+     * @return java.util.List<java.lang.String>
+     **/
+    public List<String> hMultiGet(String key, List<String> items) {
+        return redisTemplate.opsForHash().multiGet(key, items);
+    }
+
+    /**
+     * HashSet
+     *
+     * @param key 键
+     * @param map 对应多个键值
+     * @return true 成功 false 失败
+     */
+    public boolean hmset(String key, Map<String, Object> map) {
+        redisTemplate.opsForHash().putAll(key, map);
+        return true;
+    }
+    /**
+     * HashSet 并设置时间
+     *
+     * @param key  键
+     * @param map  对应多个键值
+     * @param time 时间(秒)
+     * @return true成功 false失败
+     */
+    public boolean hmset(String key, Map<String, Object> map, long time) {
+        redisTemplate.opsForHash().putAll(key, map);
+        if (time > 0) {
+            expire(key, time);
+        }
+        return true;
+    }
+    /**
+     * 向一张hash表中放入数据,如果不存在将创建
+     *
+     * @param key   键
+     * @param item  项
+     * @param value 值
+     * @return true 成功 false失败
+     */
+    public boolean hset(String key, String item, Object value) {
+        redisTemplate.opsForHash().put(key, item, value);
+        return true;
+    }
+    /**
+     * 向一张hash表中放入数据,如果不存在将创建
+     *
+     * @param key   键
+     * @param item  项
+     * @param value 值
+     * @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
+     * @return true 成功 false失败
+     */
+    public boolean hset(String key, String item, Object value, long time) {
+        redisTemplate.opsForHash().put(key, item, value);
+        if (time > 0) {
+            expire(key, time);
+        }
+        return true;
+    }
+    /**
+     * 删除hash表中的值
+     *
+     * @param key  键 不能为null
+     * @param item 项 可以使多个 不能为null
+     */
+    public void hdel(String key, Object... item) {
+        redisTemplate.opsForHash().delete(key, item);
+    }
+    /**
+     * 判断hash表中是否有该项的值
+     *
+     * @param key  键 不能为null
+     * @param item 项 不能为null
+     * @return true 存在 false不存在
+     */
+    public boolean hHasKey(String key, String item) {
+        return redisTemplate.opsForHash().hasKey(key, item);
+    }
+    /**
+     * hash递增 如果不存在,就会创建一个 并把新增后的值返回
+     *
+     * @param key  键
+     * @param item 项
+     * @param by   要增加几(大于0)
+     * @return
+     */
+    public double hincr(String key, String item, double by) {
+        return redisTemplate.opsForHash().increment(key, item, by);
+    }
+    /**
+     * hash递减
+     *
+     * @param key  键
+     * @param item 项
+     * @param by   要减少记(小于0)
+     * @return
+     */
+    public double hdecr(String key, String item, double by) {
+        return redisTemplate.opsForHash().increment(key, item, -by);
+    }
+    // ============================set=============================
+    /**
+     * 根据key获取Set中的所有值
+     *
+     * @param key 键
+     * @return
+     */
+    public Set<Object> sGet(String key) {
+        return redisTemplate.opsForSet().members(key);
+    }
+    /**
+     * 根据value从一个set中查询,是否存在
+     *
+     * @param key   键
+     * @param value 值
+     * @return true 存在 false不存在
+     */
+    public boolean sHasKey(String key, Object value) {
+        return redisTemplate.opsForSet().isMember(key, value);
+    }
+    /**
+     * 将数据放入set缓存
+     *
+     * @param key    键
+     * @param values 值 可以是多个
+     * @return 成功个数
+     */
+    public long sSet(String key, Object... values) {
+        return redisTemplate.opsForSet().add(key, values);
+    }
+    /**
+     * 将set数据放入缓存
+     *
+     * @param key    键
+     * @param time   时间(秒)
+     * @param values 值 可以是多个
+     * @return 成功个数
+     */
+    public long sSet(String key, long time, Object... values) {
+        Long count = redisTemplate.opsForSet().add(key, values);
+        if (time > 0)
+            expire(key, time);
+        return count;
+    }
+    /**
+     * 获取set缓存的长度
+     *
+     * @param key 键
+     * @return
+     */
+    public long sGetSize(String key) {
+        return redisTemplate.opsForSet().size(key);
+    }
+
+    /**
+     * 获取set缓存的长度
+     *
+     * @param key 键
+     * @return
+     */
+    public boolean sExists(String key, Object value) {
+        return redisTemplate.opsForSet().isMember(key, value);
+    }
+
+    /**
+     * 移除值为value的
+     *
+     * @param key    键
+     * @param values 值 可以是多个
+     * @return 移除的个数
+     */
+    public long setRemove(String key, Object... values) {
+        return redisTemplate.opsForSet().remove(key, values);
+    }
+    // ===============================list=================================
+    /**
+     * 获取list缓存的内容
+     *
+     * @param key   键
+     * @param start 开始
+     * @param end   结束 0 到 -1代表所有值
+     * @return
+     */
+    public List<Object> lGet(String key, long start, long end) {
+        return redisTemplate.opsForList().range(key, start, end);
+    }
+    /**
+     * 获取list缓存的长度
+     *
+     * @param key 键
+     * @return
+     */
+    public long lGetSize(String key) {
+        return redisTemplate.opsForList().size(key);
+    }
+    /**
+     * 通过索引 获取list中的值
+     *
+     * @param key   键
+     * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
+     * @return
+     */
+    public Object lGetIndex(String key, long index) {
+        return redisTemplate.opsForList().index(key, index);
+    }
+    /**
+     * 将list放入缓存
+     * @param key   键
+     * @param value 值
+     * @return
+     */
+    public boolean lRightPush(String key, Object value) {
+        redisTemplate.opsForList().rightPush(key, value);
+        return true;
+    }
+    /**
+     * 将list放入缓存
+     *
+     * @param key   键
+     * @param value 值
+     * @param time  时间(秒)
+     * @return
+     */
+    public boolean lRightPush(String key, Object value, long time) {
+        redisTemplate.opsForList().rightPush(key, value);
+        if (time > 0)
+            expire(key, time);
+        return true;
+    }
+    /**
+     * 将list放入缓存
+     *
+     * @param key   键
+     * @param value 值
+     * @return
+     */
+    public boolean lRightPushAll(String key, List<Object> value) {
+        redisTemplate.opsForList().rightPushAll(key, value);
+        return true;
+    }
+
+    /**
+     * 将list放入缓存
+     *
+     * @param key   键
+     * @param value 值
+     * @param time  时间(秒)
+     * @return
+     */
+    public boolean lRightPushAll(String key, List<Object> value, long time) {
+        redisTemplate.opsForList().rightPushAll(key, value);
+        if (time > 0)
+            expire(key, time);
+        return true;
+    }
+
+    /**
+     * 将list放入缓存
+     *
+     * @param key   键
+     * @param value 值
+     * @return
+     */
+    public boolean lLeftPushAll(String key, List<Object> value) {
+        redisTemplate.opsForList().leftPushAll(key, value);
+        return true;
+    }
+
+    /**
+     * 将list放入缓存
+     *
+     * @param key   键
+     * @param value 值
+     * @return
+     */
+    public boolean lLeftPush(String key, String value) {
+        redisTemplate.opsForList().leftPush(key, value);
+        return true;
+    }
+
+    /**
+     *
+     * @param key   键
+     * @return
+     */
+    public String lLeftPop(String key) {
+        return (String)redisTemplate.opsForList().leftPop(key);
+    }
+
+    /**
+     * 根据索引修改list中的某条数据
+     *
+     * @param key   键
+     * @param index 索引
+     * @param value 值
+     * @return
+     */
+    public boolean lUpdateByIndex(String key, long index, Object value) {
+        redisTemplate.opsForList().set(key, index, value);
+        return true;
+    }
+    /**
+     * 移除N个值为value
+     *
+     * @param key   键
+     * @param count 移除多少个
+     * @param value 值
+     * @return 移除的个数
+     */
+    public long lRemove(String key, long count, Object value) {
+        return redisTemplate.opsForList().remove(key, count, value);
+    }
+
+    /**
+     * 移除N个值为value
+     *
+     * @param pattern   键
+     * @return 移除的个数
+     */
+    public Set<String> keys(String pattern) {
+        return redisTemplate.keys(pattern);
+    }
+
+    public void expire(String key,Duration time){
+        redisTemplate.expire(key, time);
+    }
+}

+ 47 - 0
src/main/resources/application-dev.yml

@@ -0,0 +1,47 @@
+spring:
+  application:
+    name: 4dkankan-project-tieta
+  rabbitmq:
+    host: 10.180.22.47
+    port: 5672
+    username: User_CHNTZCGL_ZYAPP_002
+    password: ZYAPP002@VR
+    virtual-host: Vhost_CHNTZCGL_ZYAPP_002
+    connection-timeout: 0
+    listener:
+      simple:
+        prefetch: 1
+        max-concurrency: 1
+        acknowledge-mode: manual #开启消费者手动确认
+    #开启消息投递确认机制
+    publisher-confirm-type: correlated
+  datasource:
+    url: jdbc:oracle:thin:@//10.180.41.39:1521/resdb
+    username: RES_VR
+    password: IDCqawsed@123.
+#    username: RES_VR
+#    password: IDCqawsed@123.
+    driver-class-name: oracle.jdbc.OracleDriver
+  redis:
+    timeout: 6000ms
+    password: Qwt@1620b!v
+    cluster:
+      nodes:
+        - 10.180.22.54:7000
+mybatis-plus:
+  mapper-locations: classpath:mapper/*Mapper.xml
+  configuration:
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+
+fdfs:
+  sysCode: CT00017
+  address: http://10.180.22.41:8761
+  api:
+    getSignature: /ChinatowerFileService/getSignature
+    uploadFile: /ChinatowerFileService/uploadFile/
+
+
+
+
+
+

+ 15 - 3
src/main/resources/application-test.yml

@@ -16,10 +16,22 @@ spring:
     #开启消息投递确认机制
     publisher-confirm-type: correlated
   datasource:
-    url: jdbc:oracle:thin:@//8.135.106.227:1521/helowin
-    username: FDKK
-    password: qawsed@123.
+    url: jdbc:oracle:thin:@//10.180.41.37:1521/resdb
+    username: RES_FILE
+    password: qNQVkH3YbA
+#    username: RES_VR
+#    password: IDCqawsed@123.
     driver-class-name: oracle.jdbc.OracleDriver
+  redis:
+    timeout: 6000ms
+    password: Qwt@1620b!v
+    cluster:
+      nodes:
+        - 10.180.22.54:7000
+mybatis-plus:
+  mapper-locations: classpath:mapper/*Mapper.xml
+  configuration:
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
 
 
 

+ 1 - 1
src/main/resources/logback-spring.xml

@@ -7,7 +7,7 @@
 
 	<contextName>logback</contextName>
 	<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
-	<property name="log.path" value="/mnt/backend/4dkankan/push/logs" />
+	<property name="log.path" value="/mnt/docker/4dkankan/scene_push/logs" />
 
 	<!-- 彩色日志 -->
 	<!-- 彩色日志依赖的渲染类 -->

+ 34 - 0
src/main/resources/mapper/FullphotoFileindexMapper.xml

@@ -0,0 +1,34 @@
+<?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.project.tieta.mapper.FullphotoFileindexMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.fdkankan.project.tieta.entity.FullphotoFileindex">
+        <result column="PROVINCE_ID" property="provinceId" />
+        <result column="REGION_ID" property="regionId" />
+        <result column="STATION_CODE" property="stationCode" />
+        <result column="ENTITY_ID" property="entityId" />
+        <result column="FILE_NAME" property="fileName" />
+        <result column="FILE_MD5" property="fileMd5" />
+        <result column="FILE_TYPE" property="fileType" />
+        <result column="PIC_UUID" property="picUuid" />
+        <result column="UP_TIME" property="upTime" />
+        <result column="UP_USER" property="upUser" />
+        <result column="FILE_SIZE" property="fileSize" />
+        <result column="FILEID" property="fileid" />
+        <result column="RECORD_ID" property="recordId" />
+        <result column="UPLOAD_ID" property="uploadId" />
+        <result column="STATUS" property="status" />
+        <result column="FILE_URL" property="fileUrl" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        PROVINCE_ID, REGION_ID, STATION_CODE, ENTITY_ID, FILE_NAME, FILE_MD5, FILE_TYPE, PIC_UUID, UP_TIME, UP_USER, FILE_SIZE, FILEID, RECORD_ID, UPLOAD_ID, STATUS, FILE_URL
+    </sql>
+
+    <select id="pageStationCodeAndEntityId" resultMap="BaseResultMap">
+        select DISTINCT t.STATION_CODE, t.ENTITY_ID from T_FULLPHOTO_FILEINDEX t where t.FILE_TYPE = '11' and t.status = 1
+    </select>
+
+</mapper>