فهرست منبع

Merge branch 'master' of http://192.168.0.115:3000/4dkankan-v4/project-tieta-convert

# Conflicts:
#	src/main/java/com/fdkankan/modeldemo/utils/CreateObjUtil.java
dengsixing 4 ماه پیش
والد
کامیت
daef465938
33فایلهای تغییر یافته به همراه1559 افزوده شده و 324 حذف شده
  1. 48 32
      pom.xml
  2. 2 0
      src/main/java/com/fdkankan/modeldemo/Application.java
  3. 2 0
      src/main/java/com/fdkankan/modeldemo/bean/SceneJsonBean.java
  4. 3 1
      src/main/java/com/fdkankan/modeldemo/constant/Constant.java
  5. 39 0
      src/main/java/com/fdkankan/modeldemo/controller/SceneController.java
  6. 7 4
      src/main/java/com/fdkankan/modeldemo/entity/Scene.java
  7. 66 0
      src/main/java/com/fdkankan/modeldemo/entity/SceneConvertLog.java
  8. 7 4
      src/main/java/com/fdkankan/modeldemo/entity/SceneFileMapping.java
  9. 185 183
      src/main/java/com/fdkankan/modeldemo/generator/MappingGeneratorOracle.java
  10. 15 0
      src/main/java/com/fdkankan/modeldemo/httpclient/HttpClient.java
  11. 16 0
      src/main/java/com/fdkankan/modeldemo/mapper/SceneConvertLogMapper.java
  12. 195 33
      src/main/java/com/fdkankan/modeldemo/mq/ConvertListener.java
  13. 16 0
      src/main/java/com/fdkankan/modeldemo/service/SceneConvertLogService.java
  14. 3 1
      src/main/java/com/fdkankan/modeldemo/service/SceneFileMappingService.java
  15. 20 0
      src/main/java/com/fdkankan/modeldemo/service/impl/SceneConvertLogServiceImpl.java
  16. 4 2
      src/main/java/com/fdkankan/modeldemo/service/impl/SceneFileMappingServiceImpl.java
  17. 265 42
      src/main/java/com/fdkankan/modeldemo/utils/ConvertUtil.java
  18. 50 5
      src/main/java/com/fdkankan/modeldemo/utils/CreateObjUtil.java
  19. 20 2
      src/main/java/com/fdkankan/modeldemo/utils/FdfsUtil.java
  20. 26 0
      src/main/java/com/fdkankan/modeldemo/utils/HttpUtilExt.java
  21. 40 0
      src/main/java/com/fdkankan/rabbitmq/callback/ProducerCallback.java
  22. 119 0
      src/main/java/com/fdkankan/rabbitmq/config/RabbitMqConfig.java
  23. 112 0
      src/main/java/com/fdkankan/rabbitmq/util/RabbitMqProducer.java
  24. 75 0
      src/main/java/com/fdkankan/redis/RedisClient.java
  25. 56 0
      src/main/resources/application-dev.yml
  26. 56 0
      src/main/resources/application-preprod.yml
  27. 56 0
      src/main/resources/application-prod.yml
  28. 29 9
      src/main/resources/application-test.yml
  29. 2 3
      src/main/resources/application.yml
  30. 1 1
      src/main/resources/logback-spring.xml
  31. 22 0
      src/main/resources/mapper/SceneConvertLogMapper.xml
  32. 1 1
      src/main/resources/mapper/SceneFileMappingMapper.xml
  33. 1 1
      src/main/resources/mapper/SceneMapper.xml

+ 48 - 32
pom.xml

@@ -12,27 +12,13 @@
   </parent>
 
   <groupId>com.fdkankan.model</groupId>
-  <artifactId>4dkankan-utils-model-demo</artifactId>
+  <artifactId>project-tieta-convert</artifactId>
   <version>1.0-SNAPSHOT</version>
 
   <name>4dkankan-utils-model-demo</name>
   <!-- FIXME change it to the project's website -->
   <url>http://www.example.com</url>
 
-  <repositories>
-    <repository>
-      <id>releases</id>
-      <url>http://192.168.0.115:8081/nexus-2.14.2-01/content/repositories/releases/</url>
-    </repository>
-    <repository>
-      <id>snapshots</id>
-      <url>http://192.168.0.115:8081/nexus-2.14.2-01/content/repositories/snapshots/</url>
-    </repository>
-    <repository>
-      <id>nexus-aliyun</id>
-      <url>http://maven.aliyun.com/nexus/content/groups/public</url>
-    </repository>
-  </repositories>
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -74,11 +60,17 @@
     </dependency>
 
     <dependency>
-      <groupId>com.fdkankan</groupId>
-      <artifactId>4dkankan-utils-rabbitmq</artifactId>
-      <version>3.0.0-SNAPSHOT</version>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-amqp</artifactId>
+      <version>2.3.12.RELEASE</version>
     </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>
@@ -101,23 +93,50 @@
       <version>1.3.6</version>
     </dependency>
 
+<!--    <dependency>-->
+<!--      <groupId>com.oracle</groupId>-->
+<!--      <artifactId>ojdbc6</artifactId>-->
+<!--      <version>11.2.0.3</version>-->
+<!--    </dependency>-->
+
+<!--    <dependency>-->
+<!--      <groupId>com.oracle.ojdbc</groupId>-->
+<!--      <artifactId>ojdbc8</artifactId>-->
+<!--      <version>19.3.0.0</version>-->
+<!--    </dependency>-->
+
+<!--    <dependency>-->
+<!--      <groupId>cn.easyproject</groupId>-->
+<!--      <artifactId>orai18n</artifactId>-->
+<!--      <version>12.1.0.2.0</version>-->
+<!--      <scope>provided</scope>-->
+<!--    </dependency>-->
+
     <dependency>
-      <groupId>com.oracle</groupId>
-      <artifactId>ojdbc6</artifactId>
-      <version>11.2.0.3</version>
+      <groupId>com.chinatower.product.chinatower_visual3d</groupId>
+      <artifactId>vastbase</artifactId>
+      <version>1.0</version>
     </dependency>
+
+
     <!--mybatis-plus整合依赖-->
     <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>
+
+    <dependency>
+      <groupId>com.dtflys.forest</groupId>
+      <artifactId>forest-spring-boot-starter</artifactId>
+      <version>1.5.36</version>
     </dependency>
 
     <!-- freemarker 说明:mybatis-plus逆向工程需要freemarker模板引擎 -->
@@ -161,7 +180,7 @@
 <!--      </plugin>-->
 <!--    </plugins>-->
 
-    <finalName>4dkankan-center-convert</finalName>
+    <finalName>convert</finalName>
 
     <plugins>
       <plugin>
@@ -189,15 +208,12 @@
 
   </build>
 
-  <distributionManagement>
+  <repositories>
     <repository>
-      <id>releases</id>
-      <url>http://192.168.0.115:8081/nexus-2.14.2-01/content/repositories/releases/</url>
+      <id>chinatower</id>
+      <name>铁塔</name>
+      <url>http://10.38.77.5:8081/repository/maven-public/</url>
     </repository>
 
-    <snapshotRepository>
-      <id>snapshots</id>
-      <url>http://192.168.0.115:8081/nexus-2.14.2-01/content/repositories/snapshots/</url>
-    </snapshotRepository>
-  </distributionManagement>
+  </repositories>
 </project>

+ 2 - 0
src/main/java/com/fdkankan/modeldemo/Application.java

@@ -1,5 +1,6 @@
 package com.fdkankan.modeldemo;
 
+import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.context.annotation.ComponentScan;
@@ -9,6 +10,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
 @SpringBootApplication
 @EnableScheduling
 @ComponentScan(basePackages = {"com.fdkankan.*"})
+@MapperScan("com.fdkankan.modeldemo.mapper")
 @EnableAsync
 public class Application {
     public static void main(String[] args) {

+ 2 - 0
src/main/java/com/fdkankan/modeldemo/bean/SceneJsonBean.java

@@ -228,5 +228,7 @@ public class SceneJsonBean {
      */
     private JSONObject started;
 
+    private Integer subgroup;
+
 
 }

+ 3 - 1
src/main/java/com/fdkankan/modeldemo/constant/Constant.java

@@ -2,7 +2,7 @@ package com.fdkankan.modeldemo.constant;
 
 public class Constant {
 
-    public static final String QUEUE_SCENE_CONVERT = "queue-scene-convert";
+    public static final String QUEUE_SCENE_CONVERT = "queue-scene-convert-2";
 
     public static final String DATA_VIEW_PATH =  "scene_view_data/%s/data/";
     /**
@@ -10,6 +10,8 @@ public class Constant {
      */
     public static final String IMG_VIEW_PATH =  "scene_view_data/%s/images/";
 
+    public static final String REDIS_SCENE_CONVERT_ING = "scene:converting:%s";
+
 
 
 }

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

@@ -0,0 +1,39 @@
+package com.fdkankan.modeldemo.controller;
+
+
+import com.fdkankan.modeldemo.bean.ResultData;
+import com.fdkankan.modeldemo.service.SceneConvertLogService;
+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;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author dsx
+ * @since 2024-06-25
+ */
+@RestController
+@RequestMapping("/convert")
+public class SceneController {
+
+    @Autowired
+    private SceneConvertLogService sceneConvertLogService;
+
+    @GetMapping(value = "/ping")
+    public ResultData ping(){
+        return ResultData.ok();
+    }
+
+    @GetMapping(value = "/test")
+    public ResultData test(){
+        return ResultData.ok(sceneConvertLogService.list());
+    }
+
+
+
+
+}

+ 7 - 4
src/main/java/com/fdkankan/modeldemo/entity/Scene.java

@@ -57,10 +57,13 @@ public class Scene extends Model<Scene> {
     @TableField("FLOORPLANANGLE")
     private Integer floorplanangle;
 
+    @TableField("SUBGROUP")
+    private Integer subgroup;
 
-    @Override
-    protected Serializable pkVal() {
-        return this.id;
-    }
+
+//    @Override
+//    protected Serializable pkVal() {
+//        return this.id;
+//    }
 
 }

+ 66 - 0
src/main/java/com/fdkankan/modeldemo/entity/SceneConvertLog.java

@@ -0,0 +1,66 @@
+package com.fdkankan.modeldemo.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import java.util.Date;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ *
+ * </p>
+ *
+ * @author dsx
+ * @since 2024-07-02
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@TableName("T_SCENE_CONVERT_LOG")
+public class SceneConvertLog extends Model<SceneConvertLog> {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "ID", type = IdType.AUTO)
+    private String id;
+
+    @TableField("STATION_CODE")
+    private String stationCode;
+
+    @TableField("ENTITY_ID")
+    private String entityId;
+
+    /**
+     * 0-失败,1-成功
+     */
+    @TableField("STATUS")
+    private String status;
+
+    @TableField("CREATE_TIME")
+    private Date createTime;
+
+    /**
+     * 备注
+     */
+    @TableField("REMARK")
+    private String remark;
+
+    /**
+     * 耗时
+     */
+    @TableField("TIME_CONSUMING")
+    private String timeConsuming;
+
+
+//    @Override
+//    protected Serializable pkVal() {
+//        return this.id;
+//    }
+
+}

+ 7 - 4
src/main/java/com/fdkankan/modeldemo/entity/SceneFileMapping.java

@@ -41,10 +41,13 @@ public class SceneFileMapping extends Model<SceneFileMapping> {
     @TableField("URL")
     private String url;
 
+    @TableField("SUBGROUP")
+    private Integer subgroup;
 
-    @Override
-    protected Serializable pkVal() {
-        return this.id;
-    }
+
+//    @Override
+//    protected Serializable pkVal() {
+//        return this.id;
+//    }
 
 }

+ 185 - 183
src/main/java/com/fdkankan/modeldemo/generator/MappingGeneratorOracle.java

@@ -1,186 +1,188 @@
-package com.fdkankan.modeldemo.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\\modeldemo\\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.modeldemo.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\\modeldemo\\generator";
+//	/**
+//	 * 生成代码输出的包名
+//	 * <p>
+//	 * 总包名,后续生成的 Mapper,Service 等将在该包下生成子包
+//	 * </p>
+//	 */
+//	private static final String PACKAGE = "com.fdkankan.modeldemo";
+//	/**
+//	 * JDBC URL 说明: url地址前需要加上@,否则会报错
+//	 */
+//
+//	private static final String JDBC_URL = "jdbc:oracle:thin:@//10.180.41.39:1521/resdb";
+//	/**
+//	 * 数据库账户
+//	 */
+//	private static final String DB_USERNAME = "RES_VR";
+//	/**
+//	 * 数据库账户密码
+//	 */
+//	private static final String DB_PASSWORD = "IDCqawsed@123.";
+//
+//	/**
+//	 * 执行即可生成代码 需要添加 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_");
-		strategyConfig.setInclude("t_test");
-		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);
+//		// 设置 ID 类型
+//		globalConfig.setIdType(IdType.AUTO);
+//		globalConfig.setDateType(DateType.ONLY_DATE);
+////		// 生成基本 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;
+//	}
+//}
+//

+ 15 - 0
src/main/java/com/fdkankan/modeldemo/httpclient/HttpClient.java

@@ -0,0 +1,15 @@
+package com.fdkankan.modeldemo.httpclient;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.dtflys.forest.annotation.JSONBody;
+import com.dtflys.forest.annotation.Post;
+import com.dtflys.forest.annotation.Var;
+
+public interface HttpClient {
+
+    @Post(url = "{url}", connectTimeout = 30000,  readTimeout = 30000, maxRetryInterval = 3)
+    JSONObject postJson(@Var("url") String url, @JSONBody Object object);
+
+
+}

+ 16 - 0
src/main/java/com/fdkankan/modeldemo/mapper/SceneConvertLogMapper.java

@@ -0,0 +1,16 @@
+package com.fdkankan.modeldemo.mapper;
+
+import com.fdkankan.modeldemo.entity.SceneConvertLog;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author dsx
+ * @since 2024-07-02
+ */
+public interface SceneConvertLogMapper extends BaseMapper<SceneConvertLog> {
+
+}

+ 195 - 33
src/main/java/com/fdkankan/modeldemo/mq/ConvertListener.java

@@ -1,19 +1,28 @@
 package com.fdkankan.modeldemo.mq;
 
+import cn.hutool.core.date.TimeInterval;
+import cn.hutool.core.exceptions.ExceptionUtil;
+import cn.hutool.core.img.ImgUtil;
 import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.ZipUtil;
 import cn.hutool.http.HttpUtil;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.fdkankan.modeldemo.bean.SceneEditControlsBean;
 import com.fdkankan.modeldemo.bean.SceneJsonBean;
 import com.fdkankan.modeldemo.constant.Constant;
 import com.fdkankan.modeldemo.entity.Scene;
+import com.fdkankan.modeldemo.entity.SceneConvertLog;
 import com.fdkankan.modeldemo.entity.SceneFileMapping;
+import com.fdkankan.modeldemo.service.SceneConvertLogService;
 import com.fdkankan.modeldemo.service.SceneFileMappingService;
 import com.fdkankan.modeldemo.service.SceneService;
 import com.fdkankan.modeldemo.utils.ConvertUtil;
 import com.fdkankan.modeldemo.utils.FdfsUtil;
+import com.fdkankan.modeldemo.utils.HttpUtilExt;
+import com.fdkankan.redis.RedisClient;
 import com.rabbitmq.client.Channel;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.amqp.core.Message;
@@ -23,7 +32,10 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
+import java.io.File;
 import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Date;
 import java.util.Map;
 import java.util.Objects;
 
@@ -39,6 +51,8 @@ import java.util.Objects;
 @Component
 public class ConvertListener{
 
+    public final static String baseZipPath = "/mnt/scene/convert/";
+
     @Autowired
     private ConvertUtil convertUtil;
     @Resource
@@ -48,55 +62,203 @@ public class ConvertListener{
     @Autowired
     private SceneService sceneService;
 
+    @Autowired
+    private SceneConvertLogService sceneConvertLogService;
+    @Resource
+    private RedisClient redisClient;
+
+//    @RabbitListener(
+//            queuesToDeclare = @Queue(Constant.QUEUE_SCENE_CONVERT),
+//            concurrency = "1"
+//    )
+//    public void buildObjScenePreHandler(Channel channel, Message message) throws Exception {
+//        String roomId = null;
+//        try {
+//            String msg = new String(message.getBody(), StandardCharsets.UTF_8);
+//            log.info("msg:{}", msg);
+//            JSONObject jsonObject = JSON.parseObject(msg);
+//            //roomId
+//            roomId = jsonObject.getString("roomId");
+//            String zipUrl = jsonObject.getString("zipUrl");
+//            String zipName = FileUtil.getName(zipUrl);
+//            String dirName = FileUtil.getPrefix(zipName);
+//            log.info("zipUrl:{}", zipUrl);
+//            //下载压缩包
+//            String baseZipPath = "/mnt/scene/convert/";
+//            FileUtil.mkdir(baseZipPath);
+//            HttpUtil.downloadFile(zipUrl, baseZipPath);
+////            FileUtil.copy(zipUrl, baseZipPath, true);
+//
+//            String localZipPath = baseZipPath + zipName;
+//            ZipUtil.unzip(localZipPath, baseZipPath);
+//
+//            String targetPath = "/oss/4dkankan/scene_view_data/" + roomId + "/";
+//            String dataSource = baseZipPath + dirName + "/";
+//            Map<String, String> uploadFileMap = convertUtil.convert(dataSource, roomId);
+//            String finalRoomId = roomId;
+//            uploadFileMap.keySet().stream().forEach(key->{
+//
+//                SceneFileMapping sceneFileMapping = sceneFileMappingService.getByNumAndKey(finalRoomId, key);
+//                if(Objects.isNull(sceneFileMapping)){
+//                    sceneFileMapping = new SceneFileMapping();
+//                }
+//                Map<String, String> mapping = fdfsUtil.uploadFile(uploadFileMap.get(key));
+//                sceneFileMapping.setNum(finalRoomId);
+//                sceneFileMapping.setFileid(mapping.get("file_id"));
+//                sceneFileMapping.setUrl(mapping.get("http_url"));
+//                sceneFileMapping.setKey(key);
+//                sceneFileMappingService.saveOrUpdate(sceneFileMapping);
+//            });
+//
+//        }catch (Exception e){
+//            log.error("convert fail, roomId:{}", roomId, e);
+//        }
+//
+//        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+//
+//
+//    }
+
     @RabbitListener(
             queuesToDeclare = @Queue(Constant.QUEUE_SCENE_CONVERT),
             concurrency = "1"
     )
     public void buildObjScenePreHandler(Channel channel, Message message) throws Exception {
-        String roomId = null;
+        //开始急事
+        TimeInterval timeInterval = new TimeInterval();
+        timeInterval.start();
+
+        String messageId = message.getMessageProperties().getMessageId();
+        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+
+        String stationCode = null;
+        String entityId = null;
+        JSONArray fileList = null;
+        SceneConvertLog sceneConvertLog = new SceneConvertLog();
+        String dataSource = null;
+        String convertIngKey = null;
         try {
             String msg = new String(message.getBody(), StandardCharsets.UTF_8);
             log.info("msg:{}", msg);
             JSONObject jsonObject = JSON.parseObject(msg);
-            //roomId
-            roomId = jsonObject.getString("roomId");
-            String zipUrl = jsonObject.getString("zipUrl");
-            String zipName = FileUtil.getName(zipUrl);
-            String dirName = FileUtil.getPrefix(zipName);
-            log.info("zipUrl:{}", zipUrl);
-            //下载压缩包
-            String baseZipPath = "/mnt/scene/convert/";
-            FileUtil.mkdir(baseZipPath);
-            HttpUtil.downloadFile(zipUrl, baseZipPath);
-//            FileUtil.copy(zipUrl, baseZipPath, true);
-
-            String localZipPath = baseZipPath + zipName;
-            ZipUtil.unzip(localZipPath, baseZipPath);
-
-            String targetPath = "/oss/4dkankan/scene_view_data/" + roomId + "/";
-            String dataSource = baseZipPath + dirName + "/";
-            Map<String, String> uploadFileMap = convertUtil.convert(dataSource, roomId);
-            String finalRoomId = roomId;
-            uploadFileMap.keySet().stream().forEach(key->{
-
-                SceneFileMapping sceneFileMapping = sceneFileMappingService.getByNumAndKey(finalRoomId, key);
-                if(Objects.isNull(sceneFileMapping)){
-                    sceneFileMapping = new SceneFileMapping();
+            stationCode = jsonObject.getString("stationCode");
+            entityId = jsonObject.getString("entityId");
+            fileList = jsonObject.getJSONArray("fileList");
+            convertIngKey = String.format(Constant.REDIS_SCENE_CONVERT_ING, messageId);
+            String convert = redisClient.get(convertIngKey);
+            log.info("-----------------convert:{}-----------------", convert);
+            if(StrUtil.isNotEmpty(convert)){//正在转换,直接丢弃
+                log.warn("场景正在转换,此消息丢弃, stationCode:{}, entityId:{}", stationCode, entityId);
+                convertIngKey = null;
+                return;
+            }
+            redisClient.add(convertIngKey, stationCode + "_" + entityId, 60 * 60 * 1000L);
+
+            sceneConvertLog.setStationCode(stationCode);
+            sceneConvertLog.setEntityId(entityId);
+            sceneConvertLog.setCreateTime(new Date());
+
+            //校验文件是否齐全
+            boolean exists512 = fileList.stream().anyMatch(v -> {
+                JSONObject obj = (JSONObject) v;
+                return "1".equals(obj.getString("fileType"));
+            });
+
+            boolean exists4k = fileList.stream().anyMatch(v -> {
+                JSONObject obj = (JSONObject) v;
+                return "2".equals(obj.getString("fileType"));
+            });
+
+            boolean exists8k = fileList.stream().anyMatch(v -> {
+                JSONObject obj = (JSONObject) v;
+                return "3".equals(obj.getString("fileType"));
+            });
+
+
+            dataSource = baseZipPath + stationCode + "_" + entityId + "/";
+            String imagePath = dataSource + "images/";
+            String dataPath = dataSource + "data/";
+            String meshPath = dataPath + "mesh/";
+            String image512Path = imagePath + "512/";
+            String image4kPath = imagePath + "4k/";
+            String image8kPath = imagePath + "8k/";
+            FileUtil.mkdir(image512Path);
+            FileUtil.mkdir(image4kPath);
+
+            fileList.stream().forEach(o->{
+                JSONObject obj = (JSONObject) o;
+                String fileName = obj.getString("fileName");
+                String fileType = obj.getString("fileType");
+                String fileUrl = obj.getString("fileUrl");
+                if("7".equals(fileType)){//vision.txt
+                    HttpUtilExt.downloadFileAndCheck(fileUrl, imagePath + fileName, 300000);
+                }
+                if("1".equals(fileType)){//512图
+                    HttpUtilExt.downloadFileAndCheck(fileUrl, image512Path + fileName, 300000);
+                }
+                if("2".equals(fileType)){//4k图
+                    HttpUtilExt.downloadFileAndCheck(fileUrl, image4kPath + fileName, 300000);
+                    if(!exists512){
+                        ImgUtil.scale(new File(image4kPath + fileName), new File(image512Path + fileName), 0.125f);
+                    }
+                }
+                if(!exists4k){//如果资源中没有4k,需要用8k图做一下像素压缩
+                    if("3".equals(fileType)){
+                        HttpUtilExt.downloadFileAndCheck(fileUrl, image8kPath + fileName, 30000);
+                        ImgUtil.scale(new File(image8kPath + fileName),new File(image4kPath + fileName), 0.5f);
+                        if(!exists512){
+                            ImgUtil.scale(new File(image8kPath + fileName),new File(image512Path + fileName), 0.0625f);
+                        }
+                    }
+                }
+                if("11".equals(fileType)){//mesh.obj
+                    HttpUtilExt.downloadFileAndCheck(fileUrl, meshPath + fileName, 300000);
+                }
+                if("5".equals(fileType)){//floorplan.json
+                    HttpUtilExt.downloadFileAndCheck(fileUrl, dataPath + fileName, 300000);
+                }
+                if("12".equals(fileType)){//scene.json
+                    HttpUtilExt.downloadFileAndCheck(fileUrl, dataPath + fileName, 300000);
                 }
-                Map<String, String> mapping = fdfsUtil.uploadFile(uploadFileMap.get(key));
-                sceneFileMapping.setNum(finalRoomId);
-                sceneFileMapping.setFileid(mapping.get("file_id"));
-                sceneFileMapping.setUrl(mapping.get("http_url"));
-                sceneFileMapping.setKey(key);
-                sceneFileMappingService.saveOrUpdate(sceneFileMapping);
             });
 
+            //转换并上传文件
+            convertUtil.convert(dataSource, entityId);
+
+            sceneConvertLog.setStatus("1");
+            sceneConvertLog.setTimeConsuming(String.valueOf(timeInterval.intervalSecond()));
+            sceneConvertLogService.save(sceneConvertLog);
+
         }catch (Exception e){
-            log.error("convert fail, roomId:{}", roomId, e);
+            log.error("convert fail, stationCode:{}, roomId:{}", stationCode, entityId, e);
+            sceneConvertLog.setStatus("0");
+            sceneConvertLog.setRemark(ExceptionUtil.stacktraceToString(e, 4000));
+            sceneConvertLog.setTimeConsuming(String.valueOf(timeInterval.intervalSecond()));
+            sceneConvertLogService.save(sceneConvertLog);
+        }finally{
+            if(dataSource != null){
+                FileUtil.del(dataSource);
+                FileUtil.del(dataSource.substring(0, dataSource.lastIndexOf("/")) + "_obj2txt");
+            }
+
+            if(StrUtil.isNotEmpty(convertIngKey)){
+                redisClient.del(convertIngKey);
+            }
         }
 
-        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+//        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+    }
 
+//    public boolean checkNead8kPic(JSONArray array){
+//        array.stream().findFirst().stream().anyMatch()
+//
+//
+//
+//    }
 
+    public static void main(String[] args) {
+        String dataSource = "110106908000001067_001102050200000038732428/";
+        System.out.println(dataSource.substring(0, dataSource.lastIndexOf("/") -1) + "_obj2txt");
     }
+
 }

+ 16 - 0
src/main/java/com/fdkankan/modeldemo/service/SceneConvertLogService.java

@@ -0,0 +1,16 @@
+package com.fdkankan.modeldemo.service;
+
+import com.fdkankan.modeldemo.entity.SceneConvertLog;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author dsx
+ * @since 2024-07-02
+ */
+public interface SceneConvertLogService extends IService<SceneConvertLog> {
+
+}

+ 3 - 1
src/main/java/com/fdkankan/modeldemo/service/SceneFileMappingService.java

@@ -3,6 +3,8 @@ package com.fdkankan.modeldemo.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fdkankan.modeldemo.entity.SceneFileMapping;
 
+import java.util.List;
+
 /**
  * <p>
  *  服务类
@@ -13,6 +15,6 @@ import com.fdkankan.modeldemo.entity.SceneFileMapping;
  */
 public interface SceneFileMappingService extends IService<SceneFileMapping> {
 
-    SceneFileMapping getByNumAndKey(String num, String key);
+    List<SceneFileMapping> getByNumAndKey(String num, Integer subgroup, String key);
 
 }

+ 20 - 0
src/main/java/com/fdkankan/modeldemo/service/impl/SceneConvertLogServiceImpl.java

@@ -0,0 +1,20 @@
+package com.fdkankan.modeldemo.service.impl;
+
+import com.fdkankan.modeldemo.entity.SceneConvertLog;
+import com.fdkankan.modeldemo.mapper.SceneConvertLogMapper;
+import com.fdkankan.modeldemo.service.SceneConvertLogService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author dsx
+ * @since 2024-07-02
+ */
+@Service
+public class SceneConvertLogServiceImpl extends ServiceImpl<SceneConvertLogMapper, SceneConvertLog> implements SceneConvertLogService {
+
+}

+ 4 - 2
src/main/java/com/fdkankan/modeldemo/service/impl/SceneFileMappingServiceImpl.java

@@ -7,6 +7,8 @@ import com.fdkankan.modeldemo.mapper.SceneFileMappingMapper;
 import com.fdkankan.modeldemo.service.SceneFileMappingService;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 /**
  * <p>
  *  服务实现类
@@ -19,7 +21,7 @@ import org.springframework.stereotype.Service;
 public class SceneFileMappingServiceImpl extends ServiceImpl<SceneFileMappingMapper, SceneFileMapping> implements SceneFileMappingService {
 
     @Override
-    public SceneFileMapping getByNumAndKey(String num, String key) {
-        return this.getOne(new LambdaQueryWrapper<SceneFileMapping>().eq(SceneFileMapping::getNum, num).eq(SceneFileMapping::getKey, key));
+    public List<SceneFileMapping> getByNumAndKey(String num, Integer subgroup, String key) {
+        return this.list(new LambdaQueryWrapper<SceneFileMapping>().eq(SceneFileMapping::getNum, num).eq(SceneFileMapping::getKey, key).eq(SceneFileMapping::getSubgroup, subgroup));
     }
 }

+ 265 - 42
src/main/java/com/fdkankan/modeldemo/utils/ConvertUtil.java

@@ -1,23 +1,28 @@
 package com.fdkankan.modeldemo.utils;
 
+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.fdkankan.modeldemo.bean.SceneEditControlsBean;
 import com.fdkankan.modeldemo.bean.SceneJsonBean;
 import com.fdkankan.modeldemo.constant.Constant;
 import com.fdkankan.modeldemo.entity.Scene;
+import com.fdkankan.modeldemo.entity.SceneFileMapping;
+import com.fdkankan.modeldemo.service.SceneFileMappingService;
 import com.fdkankan.modeldemo.service.SceneService;
+import com.google.common.collect.Lists;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import javax.annotation.Resource;
 import java.io.File;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
+import java.util.stream.Collectors;
 
 @Component
 public class ConvertUtil {
@@ -25,23 +30,101 @@ public class ConvertUtil {
     @Autowired
     private SceneService sceneService;
 
+    @Autowired
+    private SceneFileMappingService sceneFileMappingService;
+    @Resource
+    private FdfsUtil fdfsUtil;
+
+    private static String[] convertVisableHandler(JSONArray visibles, Map<Integer, String> uuidMap){
+        int size = visibles.size();
+        String[] visibleArr = new String[size];
+        for(int j = 0; j < size; j++){
+            int index = (Integer)visibles.get(j);
+            String uuid = uuidMap.get(index);
+            visibleArr[j] = uuid;
+        }
+        return visibleArr;
+    }
     public static void main(String[] args) throws Exception {
 
-        String srcPath = args[0];
-        System.out.println(srcPath);
-        String targetPath = args[1];
-        System.out.println(targetPath);
+        String sourcePath = "D:\\test\\";
+        String visionPath = "D:\\test\\images\\vision.txt";
+
+//        String visionStr = FileUtil.readUtf8String(visionPath);
+//        JSONObject visionObj = JSON.parseObject(visionStr);
+//        JSONArray array = visionObj.getJSONArray("sweepLocations");
+//        Map<Integer, String> uuidMap = new HashMap<>();
+//        for(int i = 0; i < array.size(); i++){
+//            JSONObject o = (JSONObject)array.get(i);
+//            uuidMap.put(i, o.getString("uuid"));
+//        }
+//
+//        for(int i = 0; i < array.size(); i++){
+//            JSONObject o = (JSONObject)array.get(i);
+//            JSONArray visibles = o.getJSONArray("visibles");
+//            o.put("visibles", convertVisableHandler(visibles,uuidMap));
+//
+//            JSONArray visibles2 = o.getJSONArray("visibles2");
+//            o.put("visibles2", convertVisableHandler(visibles2,uuidMap));
+//
+//            JSONArray visibles3 = o.getJSONArray("visibles3");
+//            o.put("visibles3", convertVisableHandler(visibles3,uuidMap));
+//        }
+//
+//        FileUtil.writeUtf8String(JSON.toJSONString(visionObj), visionPath);
 
-//        convert(srcPath, targetPath);
-//		scanner.close();
+
+        //生成vison.modeldata
+        String visionStr = FileUtil.readUtf8String(sourcePath + "images/vision.txt");
+        JSONObject visionObj = JSON.parseObject(visionStr);
+        JSONArray sweepLocationsArr = visionObj.getJSONArray("sweepLocations");
+        //分割中高低点位
+        Map<Integer, List<String>> visibleMap = new HashMap();
+        Map<Integer, List<JSONObject>> subgroupMap = new HashMap<>();
+        for (Object item : sweepLocationsArr) {
+            JSONObject obj = (JSONObject) item;
+            int subgroup = obj.getIntValue("subgroup");
+            List<JSONObject> jsonObjects = subgroupMap.get(subgroup);
+            if(jsonObjects == null){
+                jsonObjects = new ArrayList<>();
+                subgroupMap.put(subgroup, jsonObjects);
+            }
+            obj.put("subgroup", 0);
+            jsonObjects.add(obj);
+
+            List<String> visible = visibleMap.get(subgroup);
+            if(visible == null){
+                visible = new ArrayList<>();
+                visibleMap.put(subgroup, visible);
+            }
+            visible.add(obj.getString("uuid"));
+        }
+
+        for (Integer subgroup : subgroupMap.keySet()) {
+            List<JSONObject> jsonObjects = subgroupMap.get(subgroup);
+            List<String> uuidList = visibleMap.get(subgroup);
+            for (JSONObject jsonObject : jsonObjects) {
+                String uuid = jsonObject.getString("uuid");
+                List<String> list = Lists.newArrayList(uuidList);
+                list.remove(uuid);
+                jsonObject.put("visibles",list);
+                jsonObject.put("visibles2",list);
+                jsonObject.put("visibles3",list);
+            }
+        }
+
+        //如果是高中低场景,需要上传三份数据
+        for (Integer subgroup : subgroupMap.keySet()) {
+            //拆分vision.txt
+            String visionTxtPath = sourcePath + "images/vision" + "-" + subgroup + ".txt";
+            String visionmodeldataPath = sourcePath + "images/visionmodeldata" + "-" + subgroup + ".txt";
+            JSONObject visionTxtJson = new JSONObject();
+            visionTxtJson.put("sweepLocations", subgroupMap.get(subgroup));
+            FileUtil.writeUtf8String(visionTxtJson.toJSONString(), visionTxtPath);
+            CreateObjUtil.convertTxtToVisionmodeldata(visionTxtPath, visionmodeldataPath);
+        }
     }
 
-    /**
-     *
-     * @param sourcePath 原始资源目录
-     * @param targetPath 目标资源目录
-     * @return boolean true-转换成功  false-转换失败
-     */
     public Map<String, String> convert(String sourcePath, String num) throws Exception {
 
         Map<String, String> map = new HashMap<>();
@@ -101,21 +184,49 @@ public class ConvertUtil {
 
         //压缩成dam
         String damKey = imgViewPath + "tieta.dam";
-        String damPath = obj2TxtPath + File.separator + "results" +File.separator + "tieta.dam";
+        String damPath = obj2TxtPath + File.separator + "results" +File.separator + "dam.txt";
         CreateObjUtil.convertTxtToDam( obj2TxtPath + File.separator + "results" +File.separator+"modeldata.txt", damPath);
         map.put(damKey, damPath);
 
         //复制文件
-        if(FileUtil.exist(sourcePath + "data/" + "floorplan.json")){
-            String floorplanJson = FileUtil.readUtf8String(sourcePath + "data/" + "floorplan.json");
+        JSONObject standarFloor = null;
+        Integer maxWallNum = 0;
+        if(FileUtil.exist(sourcePath + "data/floorplan.json")){
+            String floorplanJson = FileUtil.readUtf8String(sourcePath + "data/floorplan.json");
             JSONObject jsonObject = JSON.parseObject(floorplanJson);
             Integer currentId = jsonObject.getInteger("currentId");
             if(Objects.nonNull(currentId) && currentId == 0){
                 FileUtil.del(sourcePath + "data/" + "floorplan.json");
+            }else{
+                JSONArray floors = jsonObject.getJSONArray("floors");
+                for (Object floor : floors) {
+                    JSONObject floorObj = (JSONObject) floor;
+                    Map walls = floorObj.getObject("walls", Map.class);
+                    if(walls.keySet().size() > maxWallNum){
+                        maxWallNum = walls.keySet().size();
+                        standarFloor = floorObj;
+                    }
+                }
+                //切割,按subgroup分成多份
+                for (Object floor : floors) {
+                    JSONObject floorObj = (JSONObject) floor;
+                    Integer subgroup = floorObj.getIntValue("subgroup");
+                    floorObj.put("walls", standarFloor.getJSONObject("walls"));
+                    floorObj.put("points", standarFloor.getJSONObject("points"));
+                    floorObj.put("subgroup", 0);
+                    floorObj.put("id", 0);
+                    jsonObject.replace("floors", Arrays.asList(floorObj));
+                    String floorplanPath = sourcePath + "data/floorplan" + "-" + subgroup + ".json";
+                    FileUtil.writeUtf8String(jsonObject.toJSONString(), floorplanPath);
+                }
             }
         }
+
         List<File> dataFiles = FileUtil.loopFiles(sourcePath + "data/");
         for (File dataFile : dataFiles) {
+            if(dataFile.getAbsolutePath().contains("floorplan")){
+                continue;
+            }
             map.put(dataFile.getAbsolutePath().replace(sourcePath + "data/", dataViewPath) , dataFile.getAbsolutePath());
         }
 
@@ -141,46 +252,155 @@ public class ConvertUtil {
             });
 
         }
-        map.put(imgViewPath + "vision.txt", sourcePath + "images/vision.txt");
 //            FileUtil.copy(sourcePath + "images/vision.txt", targetImagePath + "/vision.txt", true);
+        //单独上传一份全的vision.txt
+        this.uploadVisionTxt(num, sourcePath + "images/vision.txt");
 
         //生成vison.modeldata
-        CreateObjUtil.convertTxtToVisionmodeldata(sourcePath + "images/vision.txt", sourcePath + "images/vision.modeldata");
-        map.put(imgViewPath + "vision.modeldata", sourcePath + "images/vision.modeldata");
+        String visionStr = FileUtil.readUtf8String(sourcePath + "images/vision.txt");
+        JSONObject visionObj = JSON.parseObject(visionStr);
+        JSONArray sweepLocationsArr = visionObj.getJSONArray("sweepLocations");
+        //分割中高低点位
+        Map<Integer, List<String>> visibleMap = new HashMap();
+        Map<Integer, List<JSONObject>> subgroupMap = new HashMap<>();
+        for (Object item : sweepLocationsArr) {
+            JSONObject obj = (JSONObject) item;
+            int subgroup = obj.getIntValue("subgroup");
+            List<JSONObject> jsonObjects = subgroupMap.get(subgroup);
+            if(jsonObjects == null){
+                jsonObjects = new ArrayList<>();
+                subgroupMap.put(subgroup, jsonObjects);
+            }
+            obj.put("subgroup", 0);
+            jsonObjects.add(obj);
+
+            List<String> visible = visibleMap.get(subgroup);
+            if(visible == null){
+                visible = new ArrayList<>();
+                visibleMap.put(subgroup, visible);
+            }
+            visible.add(obj.getString("uuid"));
+        }
+
+        for (Integer subgroup : subgroupMap.keySet()) {
+            List<JSONObject> jsonObjects = subgroupMap.get(subgroup);
+            List<String> uuidList = visibleMap.get(subgroup);
+            for (JSONObject jsonObject : jsonObjects) {
+                String uuid = jsonObject.getString("uuid");
+                List<String> list = Lists.newArrayList(uuidList);
+                list.remove(uuid);
+                jsonObject.put("visibles",list);
+                jsonObject.put("visibles2",list);
+                jsonObject.put("visibles3",list);
+            }
+        }
+
 
         //生成场景标题
         String title = this.getTitle(num, sourcePath);
 
-        //生成scene.json
-        SceneJsonBean sceneJsonBean = this.genSceneJson(num, title);
-        FileUtil.writeUtf8String(JSON.toJSONString(sceneJsonBean), sourcePath + "data/scene.json");
-        map.put(dataViewPath + "scene.json", sourcePath + "data/scene.json");
+        //如果是高中低场景,需要上传三份数据
+        for (Integer subgroup : subgroupMap.keySet()) {
+
+            //拆分vision.txt
+            String visionTxtPath = sourcePath + "images/vision" + "-" + subgroup + ".txt";
+            String visionmodeldataPath = sourcePath + "images/visionmodeldata" + "-" + subgroup + ".txt";
+            JSONObject visionTxtJson = new JSONObject();
+            visionTxtJson.put("sweepLocations", subgroupMap.get(subgroup));
+            FileUtil.writeUtf8String(visionTxtJson.toJSONString(), visionTxtPath);
+            CreateObjUtil.convertTxtToVisionmodeldata(visionTxtPath, visionmodeldataPath);
+            map.put(imgViewPath + "vision.modeldata", visionmodeldataPath);
+            map.put(imgViewPath + "vision.txt", visionTxtPath);
+
+            //拆分floorplan.json
+            String floorplanPath = sourcePath + "data/floorplan" + "-" + subgroup + ".json";
+            if(FileUtil.exist(floorplanPath)){
+                map.put(dataViewPath + "floorplan.json", floorplanPath);
+            }
+
+            //生成scene.json
+            String sceneJsonPath = sourcePath + "data/scene" + "-" + subgroup + ".json";
+            SceneJsonBean sceneJsonBean = this.genSceneJson(num, title, subgroup);
+            FileUtil.writeUtf8String(JSON.toJSONString(sceneJsonBean), sceneJsonPath);
+            map.put(dataViewPath + "scene.json", sceneJsonPath);
+
+            String finalRoomId = num;
+            map.keySet().stream().forEach(key->{
+                List<SceneFileMapping> sceneFileMappingList = sceneFileMappingService.getByNumAndKey(finalRoomId, subgroup, key);
+                if(CollUtil.isNotEmpty(sceneFileMappingList)){
+                    List<String> deleteIds = sceneFileMappingList.stream().map(v -> v.getId()).collect(Collectors.toList());
+                    sceneFileMappingService.removeByIds(deleteIds);
+                }
+                SceneFileMapping sceneFileMapping = new SceneFileMapping();
+                Map<String, String> mapping = fdfsUtil.uploadFile(map.get(key));
+                sceneFileMapping.setNum(finalRoomId);
+                sceneFileMapping.setFileid(mapping.get("file_id"));
+                sceneFileMapping.setUrl(mapping.get("http_url"));
+                sceneFileMapping.setKey(key);
+                sceneFileMapping.setSubgroup(subgroup);
+                sceneFileMappingService.save(sceneFileMapping);
+            });
+
+
+            List<Scene> list = sceneService.list(new LambdaQueryWrapper<Scene>().eq(Scene::getNum, num).eq(Scene::getSubgroup, subgroup));
+            Scene scene = null;
+            if(CollUtil.isEmpty(list)){
+                scene = new Scene();
+            }else{
+                if(list.size() > 1){
+                    sceneService.remove(new LambdaQueryWrapper<Scene>().eq(Scene::getNum, num));
+                    scene = new Scene();
+                }else{
+                    scene = list.get(0);
+                }
+            }
+
+            scene.setTitle(title);
+            scene.setNum(num);
+            scene.setFloorlogosize(100);
+            scene.setScenekind("pano");
+            scene.setSceneresolution("4k");
+            scene.setScenefrom("realsee");
+            scene.setModelkind("dam");
+            scene.setFloorplanangle(0);
+            scene.setSubgroup(subgroup);
+            sceneService.saveOrUpdate(scene);
+        }
+
+
+//        map.put(imgViewPath + "vision.modeldata", sourcePath + "images/visionmodeldata.txt");
+
+
+
+
 
         return map;
     }
 
-    private SceneJsonBean genSceneJson(String roomId, String title){
-
-        Scene scene = sceneService.getByNum(roomId);
-        if(Objects.isNull(scene)){
-            scene = new Scene();
+    private void uploadVisionTxt(String num, String localVisionTxtPath){
+        String key = String.format(Constant.IMG_VIEW_PATH, num) + "vision.txt";
+        List<SceneFileMapping> sceneFileMappingList =  sceneFileMappingService.list(new LambdaQueryWrapper<SceneFileMapping>().eq(SceneFileMapping::getKey, key).eq(SceneFileMapping::getNum, num).eq(SceneFileMapping::getSubgroup, -1));
+        if(CollUtil.isNotEmpty(sceneFileMappingList)){
+            List<String> deleteIds = sceneFileMappingList.stream().map(v -> v.getId()).collect(Collectors.toList());
+            sceneFileMappingService.removeByIds(deleteIds);
         }
-        scene.setTitle(title);
-        scene.setNum(roomId);
-        scene.setFloorlogosize(100);
-        scene.setScenekind("pano");
-        scene.setSceneresolution("4k");
-        scene.setScenefrom("realsee");
-        scene.setModelkind("dam");
-        scene.setFloorplanangle(0);
-        sceneService.saveOrUpdate(scene);
+        SceneFileMapping sceneFileMapping = new SceneFileMapping();
+        Map<String, String> mapping = fdfsUtil.uploadFile(localVisionTxtPath);//sourcePath + "images/vision.txt"
+        sceneFileMapping.setNum(num);
+        sceneFileMapping.setFileid(mapping.get("file_id"));
+        sceneFileMapping.setUrl(mapping.get("http_url"));
+        sceneFileMapping.setKey(key);
+        sceneFileMapping.setSubgroup(-1);
+        sceneFileMappingService.save(sceneFileMapping);
+    }
 
+    private SceneJsonBean genSceneJson(String roomId, String title, Integer subgroup){
         SceneEditControlsBean sceneEditControlsBean = SceneEditControlsBean.builder()
                 .showDollhouse(1).showMap(1).showPanorama(1).showVR(1).showTitle(1).showFloorplan(1).build();
 
         SceneJsonBean sceneJsonBean = SceneJsonBean.builder()
                 .title(title).description(null)
-                .num(roomId).floorLogoSize(100).sceneKind("pano")
+                .num(roomId).subgroup(subgroup).floorLogoSize(100).sceneKind("pano")
                 .sceneResolution("4k").sceneFrom("realsee")
                 .modelKind("dam").floorPlanAngle(0).controls(sceneEditControlsBean).build();
 
@@ -196,7 +416,10 @@ public class ConvertUtil {
         String sceneJsonStr = FileUtil.readUtf8String(sceneJsonPath);
         JSONObject jsonObject = JSON.parseObject(sceneJsonStr);
         String title = jsonObject.getString("title");
-        return Objects.isNull(title) ? roomId : title;
+        if(StrUtil.isEmpty(title)){
+            return roomId;
+        }
+        return title;
     }
 
     public static void writeDataJson(String path){

+ 50 - 5
src/main/java/com/fdkankan/modeldemo/utils/CreateObjUtil.java

@@ -10,8 +10,7 @@ import com.google.protobuf.TextFormat;
 import lombok.extern.slf4j.Slf4j;
 
 import java.io.*;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
 
 @Slf4j
 public class CreateObjUtil {
@@ -34,6 +33,18 @@ public class CreateObjUtil {
 		}
 
 //		scanner.close();
+
+//		String srcFileName1 = "D:\\test\\tieta\\110106908000001067_001102050200000038732428\\modeldata.txt";
+//		String srcFileName2 = "D:\\test\\tieta\\110115908000001104_000102050000000000079651\\modeldata.txt";
+//		String srcFileName3 = "D:\\test\\tieta\\111401500010001724_500102050000000000285799\\modeldata.txt";
+//		String targetFileName1 = "D:\\test\\tieta\\110106908000001067_001102050200000038732428\\tieta.dam";
+//		String targetFileName2 = "D:\\test\\tieta\\110115908000001104_000102050000000000079651\\tieta.dam";
+//		String targetFileName3 = "D:\\test\\tieta\\111401500010001724_500102050000000000285799\\tieta.dam";
+//		CreateObjUtil.convertTxtToDam(srcFileName1,targetFileName1);
+//		CreateObjUtil.convertTxtToDam(srcFileName2,targetFileName2);
+//		CreateObjUtil.convertTxtToDam(srcFileName3,targetFileName3);
+
+		CreateObjUtil.convertTxtToVisionmodeldata("C:\\Users\\dsx\\Desktop\\vsion.txt", "C:\\Users\\dsx\\Desktop\\vsion.modeldata");
 	}
 
 	/**
@@ -148,11 +159,45 @@ public class CreateObjUtil {
 		for (Object o : sweepLocationArr) {
 			JSONObject sweepLocationObj = (JSONObject)o;
 			JSONArray visibles =  sweepLocationObj.getJSONArray("visibles");
-			int[] visiblesArr = new int[visibles.size()];
+//			int[] visiblesArr = new int[visibles.size()];
+			List<Integer> visiblesList = new ArrayList<>();
 			for(int i = 0; i < visibles.size(); i++){
-				visiblesArr[i] = uuidIndexMap.get(visibles.get(i));
+				Integer index = uuidIndexMap.get(visibles.get(i));
+				if(Objects.isNull(index)){
+					continue;
+				}
+				visiblesList.add(index);
+			}
+			sweepLocationObj.put("visibles", visiblesList);
+
+			if(sweepLocationObj.containsKey("visibles2")){
+				JSONArray visibles2 =  sweepLocationObj.getJSONArray("visibles2");
+//				int[] visiblesArr2 = new int[visibles2.size()];
+				List<Integer> visibles2List = new ArrayList<>();
+				for(int i = 0; i < visibles2.size(); i++){
+					Integer index = uuidIndexMap.get(visibles2.get(i));
+					if(Objects.isNull(index)){
+						continue;
+					}
+					visibles2List.add(index);
+				}
+				sweepLocationObj.put("visibles2", visibles2List);
 			}
-			sweepLocationObj.put("visibles", visiblesArr);
+
+			if(sweepLocationObj.containsKey("visibles3")){
+				JSONArray visibles3 =  sweepLocationObj.getJSONArray("visibles3");
+//				int[] visiblesArr3 = new int[visibles3.size()];
+				List<Integer> visibles3List = new ArrayList<>();
+				for(int i = 0; i < visibles3.size(); i++){
+					Integer index = uuidIndexMap.get(visibles3.get(i));
+					if(Objects.isNull(index)){
+						continue;
+					}
+					visibles3List.add(index);
+				}
+				sweepLocationObj.put("visibles3", visibles3List);
+			}
+
 		}
 		return JSON.toJSONString(visionJson);
 	}

+ 20 - 2
src/main/java/com/fdkankan/modeldemo/utils/FdfsUtil.java

@@ -1,10 +1,12 @@
 package com.fdkankan.modeldemo.utils;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.lang.UUID;
 import cn.hutool.http.HttpRequest;
 import cn.hutool.http.HttpResponse;
 import com.alibaba.fastjson.JSON;
 import com.fdkankan.modeldemo.bean.TietaResBean;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 
@@ -14,6 +16,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 @Component
+@Slf4j
 public class FdfsUtil {
 
     @Value("${fdfs.address}")
@@ -57,9 +60,10 @@ public class FdfsUtil {
         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);
+        HttpRequest httpRequest = HttpRequest.post(address.concat(api_uploadFile)).form(test).addHeaders(headers).timeout(120000);
         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();
@@ -73,7 +77,21 @@ public class FdfsUtil {
         String nonce = UUID.fastUUID().toString();
         String timestamp = String.valueOf(new Date().getTime());
         String signature = getSignature(nonce, timestamp);
-        return uploadFile(nonce, timestamp, signature, filePath);
+        Map<String, String> stringStringMap = null;
+        for(int i = 0; i< 5; i++){
+            try {
+                stringStringMap = uploadFile(nonce, timestamp, signature, filePath);
+                if(CollUtil.isNotEmpty(stringStringMap)){
+                    break;
+                }
+            }catch (Exception e){
+                log.warn("第{}上传文件失败,path:{}", i + 1, filePath, e);
+            }
+        }
+        if(CollUtil.isEmpty(stringStringMap)){
+            throw new RuntimeException("上传文件FASTDFS失败,path:{}" + filePath);
+        }
+        return stringStringMap;
     }
 
     public static void main(String[] args) {

+ 26 - 0
src/main/java/com/fdkankan/modeldemo/utils/HttpUtilExt.java

@@ -0,0 +1,26 @@
+package com.fdkankan.modeldemo.utils;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.http.HttpUtil;
+import lombok.extern.slf4j.Slf4j;
+import net.sf.jsqlparser.statement.create.table.Index;
+
+import java.io.File;
+
+@Slf4j
+public class HttpUtilExt extends HttpUtil {
+
+    public static void downloadFileAndCheck(String url, String localPath, int timeout){
+        for (int i = 0; i < 5; i++){
+            try {
+                downloadFile(url, new File(localPath), timeout);
+                if(FileUtil.exist(localPath) && FileUtil.size(new File(localPath)) > 0){
+                    return;
+                }
+            }catch (Exception e){
+                log.warn("第{}次文件下载失败,url{}", i+1, url);
+            }
+        }
+    }
+
+}

+ 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));
+        }
+    }
+
+
+
+}

+ 75 - 0
src/main/java/com/fdkankan/redis/RedisClient.java

@@ -0,0 +1,75 @@
+package com.fdkankan.redis;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.modeldemo.httpclient.HttpClient;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+@Component
+public class RedisClient {
+
+    public final static String url_str_add = "/redis/string/add/";
+
+    public final static String url_str_get = "/redis/string/get/";
+
+    public final static String url_str_del = "/redis/string/delete";
+
+    @Value("${redis.host}")
+    private String host;
+
+    @Value("${tieta.sysCode}")
+    private String sysCode;
+
+    @Value("${tieta.serverName}")
+    private String serverName;
+
+    @Resource
+    private HttpClient httpClient;
+
+
+     public void add(String key, String value, Long time){
+         String url = host + url_str_add;
+         Map<String, Object> params = new HashMap<>();
+         params.put("key", this.genKey(key));
+         params.put("value", value);
+         if(Objects.nonNull(time)){
+             params.put("time", time);
+         }
+         JSONObject jsonObject = httpClient.postJson(url, params);
+         if(Objects.isNull(jsonObject) || !"0".equals(jsonObject.getString("status"))){
+             throw new RuntimeException("redis add string error");
+         }
+     }
+
+    public String get(String key){
+        String url = host + url_str_get;
+        Map<String, Object> params = new HashMap<>();
+        params.put("key", this.genKey(key));
+        JSONObject jsonObject = httpClient.postJson(url, params);
+        if(Objects.isNull(jsonObject) || !"0".equals(jsonObject.getString("status"))){
+            throw new RuntimeException("redis get string error");
+        }
+        return jsonObject.getString("data");
+    }
+
+    public String del(String key){
+        String url = host + url_str_del;
+        Map<String, Object> params = new HashMap<>();
+        params.put("key", this.genKey(key));
+        JSONObject jsonObject = httpClient.postJson(url, params);
+        if(Objects.isNull(jsonObject) || !"0".equals(jsonObject.getString("status"))){
+            throw new RuntimeException("redis del string error");
+        }
+        return jsonObject.getString("data");
+    }
+
+    private String genKey(String key){
+         return sysCode + "_" + serverName + "_" + key;
+    }
+}
+

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

@@ -0,0 +1,56 @@
+spring:
+  application:
+    name: 4dkankan-center-convert
+  rabbitmq:
+    host: 10.180.22.49
+    port: 5672
+    username: User_CHNTZCGL_ZCSZHGL_003
+    password: zcszhgl03_vr
+    virtual-host: Vhost_CHNTZCGL_ZCSZHGL_003
+    connection-timeout: 0
+    listener:
+      simple:
+        prefetch: 1
+        max-concurrency: 1
+        acknowledge-mode: manual #开启消费者手动确认
+    #开启消息投递确认机制
+    publisher-confirm-type: correlated
+  datasource:
+    url: jdbc:postgresql://10.180.145.98:5432/chinatower_vr
+    username: res_vr
+    password: qawsed@123.
+    driver-class-name: org.postgresql.Driver
+    hikari:
+      maximum-pool-size: 20 #连接池最大连接数
+      minimum-idle: 5 #连接池最小连接数
+      connection-timeout: 30000
+      idle-timeout: 600000
+      max-lifetime: 1800000
+      login-timeout: 60000
+      pool-name: MyHikariCP
+      connection-test-query: SELECT 1 FROM DUAL
+
+mybatis-plus:
+  mapper-locations: classpath:mapper/*Mapper.xml
+  configuration:
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+
+tieta:
+  sysCode: CT00017
+  serverName: vrconvert
+
+fdfs:
+  sysCode: CT00017
+  address: http://10.180.22.41:8761
+  api:
+    getSignature: /ChinatowerFileService/getSignature
+    uploadFile: /ChinatowerFileService/uploadFile/
+
+redis:
+  host: http://10.180.22.54:8081
+
+
+
+
+
+

+ 56 - 0
src/main/resources/application-preprod.yml

@@ -0,0 +1,56 @@
+spring:
+  application:
+    name: 4dkankan-center-convert
+  rabbitmq:
+    host: 10.34.53.30
+    port: 5672
+    username: User_CHNTZCGL_ZCSZHGL_003
+    password: zcszhgl03_vr
+    virtual-host: Vhost_CHNTZCGL_ZCSZHGL_003
+    connection-timeout: 0
+    listener:
+      simple:
+        prefetch: 1
+        max-concurrency: 1
+        acknowledge-mode: manual #开启消费者手动确认
+    #开启消息投递确认机制
+    publisher-confirm-type: correlated
+  datasource:
+    url: jdbc:postgresql://10.161.32.224:5432/chinatower_vr
+    username: res_vr
+    password: Qwer!@#123
+    driver-class-name: org.postgresql.Driver
+    hikari:
+      maximum-pool-size: 20 #连接池最大连接数
+      minimum-idle: 5 #连接池最小连接数
+      connection-timeout: 30000
+      idle-timeout: 600000
+      max-lifetime: 1800000
+      login-timeout: 60000
+      pool-name: MyHikariCP
+      connection-test-query: SELECT 1 FROM DUAL
+
+mybatis-plus:
+  mapper-locations: classpath:mapper/*Mapper.xml
+  configuration:
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+
+tieta:
+  sysCode: CT00017
+  serverName: vrconvert
+
+fdfs:
+  sysCode: CT00017
+  address: http://10.34.53.27:8761
+  api:
+    getSignature: /ChinatowerFileService/getSignature
+    uploadFile: /ChinatowerFileService/uploadFile/
+
+redis:
+  host: http://10.34.53.34:8081
+
+
+
+
+
+

+ 56 - 0
src/main/resources/application-prod.yml

@@ -0,0 +1,56 @@
+spring:
+  application:
+    name: 4dkankan-center-convert
+  rabbitmq:
+    host: 192.168.53.58
+    port: 5672
+    username: User_CHNTZCGL_ZCSZHGL_003
+    password: zcszhgl03_vr
+    virtual-host: Vhost_CHNTZCGL_ZCSZHGL_003
+    connection-timeout: 0
+    listener:
+      simple:
+        prefetch: 1
+        max-concurrency: 1
+        acknowledge-mode: manual #开启消费者手动确认
+    #开启消息投递确认机制
+    publisher-confirm-type: correlated
+  datasource:
+    url: jdbc:postgresql://10.159.32.174:5432/chinatower_vr
+    username: res_vr
+    password: Qwer!@#123
+    driver-class-name: org.postgresql.Driver
+    hikari:
+      maximum-pool-size: 20 #连接池最大连接数
+      minimum-idle: 5 #连接池最小连接数
+      connection-timeout: 30000
+      idle-timeout: 600000
+      max-lifetime: 1800000
+      login-timeout: 60000
+      pool-name: MyHikariCP
+      connection-test-query: SELECT 1 FROM DUAL
+
+mybatis-plus:
+  mapper-locations: classpath:mapper/*Mapper.xml
+  configuration:
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+
+tieta:
+  sysCode: CT00017
+  serverName: vrconvert
+
+fdfs:
+  sysCode: CT00017
+  address: http://192.168.53.243:7356
+  api:
+    getSignature: /ChinatowerFileService/getSignature
+    uploadFile: /ChinatowerFileService/uploadFile/
+
+redis:
+  host: http://192.168.53.243:8081
+
+
+
+
+
+

+ 29 - 9
src/main/resources/application-test.yml

@@ -2,11 +2,11 @@ spring:
   application:
     name: 4dkankan-center-convert
   rabbitmq:
-    host: 10.180.22.47
+    host: 10.190.22.110
     port: 5672
-    username: User_CHNTZCGL_ZYAPP_002
-    password: ZYAPP002@VR
-    virtual-host: Vhost_CHNTZCGL_ZYAPP_002
+    username: User_CHNTZCGL_ZCSZHGL_003
+    password: zcszhgl03_vr
+    virtual-host: Vhost_CHNTZCGL_ZCSZHGL_003
     connection-timeout: 0
     listener:
       simple:
@@ -16,18 +16,38 @@ spring:
     #开启消息投递确认机制
     publisher-confirm-type: correlated
   datasource:
-    url: jdbc:oracle:thin:@//8.135.106.227:1521/helowin
-    username: FDKK
-    password: qawsed@123.
-    driver-class-name: oracle.jdbc.OracleDriver
+    url: jdbc:postgresql://10.190.134.143:5432/chinatower_vr?currentSchema=res_vr
+    username: RES_VR
+    password: Qwer!@#123
+    driver-class-name: org.postgresql.Driver
+    hikari:
+      maximum-pool-size: 20 #连接池最大连接数
+      minimum-idle: 5 #连接池最小连接数
+      connection-timeout: 30000
+      idle-timeout: 600000
+      max-lifetime: 1800000
+      login-timeout: 60000
+      pool-name: MyHikariCP
+      connection-test-query: SELECT 1
+
+mybatis-plus:
+  mapper-locations: classpath:mapper/*Mapper.xml
+  configuration:
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+
+tieta:
+  sysCode: CT00017
+  serverName: vrconvert
 
 fdfs:
   sysCode: CT00017
-  address: http://10.180.22.41:8761
+  address: http://10.190.22.106:8765
   api:
     getSignature: /ChinatowerFileService/getSignature
     uploadFile: /ChinatowerFileService/uploadFile/
 
+redis:
+  host: http://10.190.22.99:8081
 
 
 

+ 2 - 3
src/main/resources/application.yml

@@ -1,3 +1,2 @@
-spring:
-  profiles:
-    active: test
+server:
+  port: 10083

+ 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/convert/logs" />
+	<property name="log.path" value="/app/4dkankan/convert/logs" />
 
 	<!-- 彩色日志 -->
 	<!-- 彩色日志依赖的渲染类 -->

+ 22 - 0
src/main/resources/mapper/SceneConvertLogMapper.xml

@@ -0,0 +1,22 @@
+<?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.modeldemo.mapper.SceneConvertLogMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.fdkankan.modeldemo.entity.SceneConvertLog">
+        <id column="ID" property="id" />
+        <result column="STATION_CODE" property="stationCode" />
+        <result column="ENTITY_ID" property="entityId" />
+        <result column="STATUS" property="status" />
+        <result column="CREATE_TIME" property="createTime" />
+        <result column="REMARK" property="remark" />
+        <result column="TIME_CONSUMING" property="timeConsuming" />
+
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        ID, STATION_CODE, ENTITY_ID, STATUS, CRAETE_TIME, REMARK
+    </sql>
+
+</mapper>

+ 1 - 1
src/main/resources/mapper/SceneFileMappingMapper.xml

@@ -3,7 +3,7 @@
 <mapper namespace="com.fdkankan.modeldemo.mapper.SceneFileMappingMapper">
 
     <!-- 通用查询映射结果 -->
-    <resultMap id="BaseResultMap" type="com.fdkankan.project.tieta.entity.SceneFileMapping">
+    <resultMap id="BaseResultMap" type="com.fdkankan.modeldemo.entity.SceneFileMapping">
         <id column="ID" property="id" />
         <result column="NUM" property="num" />
         <result column="FILEID" property="fileid" />

+ 1 - 1
src/main/resources/mapper/SceneMapper.xml

@@ -3,7 +3,7 @@
 <mapper namespace="com.fdkankan.modeldemo.mapper.SceneMapper">
 
     <!-- 通用查询映射结果 -->
-    <resultMap id="BaseResultMap" type="com.fdkankan.project.tieta.entity.Scene">
+    <resultMap id="BaseResultMap" type="com.fdkankan.modeldemo.entity.Scene">
         <id column="ID" property="id" />
         <result column="TITLE" property="title" />
         <result column="DESCRIPTION" property="description" />