瀏覽代碼

添加计算模块代码

tianboguang 3 年之前
父節點
當前提交
6daa257419
共有 57 個文件被更改,包括 4354 次插入1 次删除
  1. 65 0
      4dkankan-center-modeling/pom.xml
  2. 2 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/ModelingApplication.java
  3. 70 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/config/MQProducerConfig.java
  4. 61 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/config/MQReceiverConfig.java
  5. 9 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/constants/RedisKey.java
  6. 35 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/constants/SysConstants.java
  7. 278 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/entity/Scene.java
  8. 95 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/entity/SceneFileBuild.java
  9. 146 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/entity/ScenePro.java
  10. 176 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/entity/SceneProEdit.java
  11. 164 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/entity/SceneProEditExt.java
  12. 137 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/entity/SceneProExt.java
  13. 144 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/entity/User.java
  14. 18 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/mapper/ISceneFileBuildMapper.java
  15. 18 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/mapper/ISceneMapper.java
  16. 18 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/mapper/ISceneProEditExtMapper.java
  17. 18 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/mapper/ISceneProEditMapper.java
  18. 18 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/mapper/ISceneProExtMapper.java
  19. 18 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/mapper/ISceneProMapper.java
  20. 18 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/mapper/IUserMapper.java
  21. 199 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/AndroidNotification.java
  22. 6 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/App.java
  23. 95 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/IOSNotification.java
  24. 103 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/PushClient.java
  25. 331 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/PushMessageConfig.java
  26. 86 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/UmengNotification.java
  27. 11 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/android/AndroidBroadcast.java
  28. 22 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/android/AndroidCustomizedcast.java
  29. 15 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/android/AndroidFilecast.java
  30. 16 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/android/AndroidGroupcast.java
  31. 16 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/android/AndroidUnicast.java
  32. 12 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/ios/IOSBroadcast.java
  33. 23 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/ios/IOSCustomizedcast.java
  34. 15 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/ios/IOSFilecast.java
  35. 16 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/ios/IOSGroupcast.java
  36. 15 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/ios/IOSUnicast.java
  37. 842 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/receiver/BuildSceneReceiver.java
  38. 19 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/ISceneFileBuildService.java
  39. 16 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/ISceneProEditExtService.java
  40. 16 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/ISceneProEditService.java
  41. 16 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/ISceneProExtService.java
  42. 21 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/ISceneProService.java
  43. 19 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/ISceneService.java
  44. 18 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/IUserService.java
  45. 29 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/impl/SceneFileBuildServiceImpl.java
  46. 20 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/impl/SceneProEditExtServiceImpl.java
  47. 20 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/impl/SceneProEditServiceImpl.java
  48. 20 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/impl/SceneProExtServiceImpl.java
  49. 35 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/impl/SceneProServiceImpl.java
  50. 24 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/impl/SceneServiceImpl.java
  51. 30 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/impl/UserServiceImpl.java
  52. 332 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/utils/ComputerUtil.java
  53. 91 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/utils/DingDingUtils.java
  54. 46 0
      4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/utils/PushMsgUtil.java
  55. 0 1
      4dkankan-center-modeling/src/main/resources/application.properties
  56. 20 0
      4dkankan-center-modeling/src/main/resources/bootstrap.yml
  57. 231 0
      4dkankan-center-modeling/src/main/resources/logback-spring.xml

+ 65 - 0
4dkankan-center-modeling/pom.xml

@@ -19,6 +19,30 @@
 
 	<dependencies>
 		<dependency>
+			<groupId>com.fdkankan</groupId>
+			<artifactId>4dkankan-common-utils</artifactId>
+			<version>2.0.0</version>
+		</dependency>
+
+		<dependency>
+			<groupId>com.fdkankan</groupId>
+			<artifactId>4dkankan-common-mq</artifactId>
+			<version>2.0.0</version>
+		</dependency>
+
+		<dependency>
+			<groupId>com.fdkankan</groupId>
+			<artifactId>4dkankan-common-db</artifactId>
+			<version>2.0.0</version>
+		</dependency>
+
+		<dependency>
+			<groupId>com.fdkankan</groupId>
+			<artifactId>4dkankan-common-redis</artifactId>
+			<version>2.0.0</version>
+		</dependency>
+
+		<dependency>
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter</artifactId>
 		</dependency>
@@ -28,6 +52,47 @@
 			<artifactId>spring-boot-starter-test</artifactId>
 			<scope>test</scope>
 		</dependency>
+		<!-- 钉钉sdk -->
+		<dependency>
+			<groupId>com.dingtalk.open</groupId>
+			<artifactId>taobao-sdk-java-auto</artifactId>
+			<version>1479188381469-20211020</version>
+		</dependency>
+		<dependency>
+			<groupId>com.google.firebase</groupId>
+			<artifactId>firebase-admin</artifactId>
+			<version>6.8.1</version>
+		</dependency>
+		<dependency>
+			<groupId>com.fdkankan</groupId>
+			<artifactId>4dkankan-sdk-oss</artifactId>
+			<version>1.0.0</version>
+		</dependency>
+		<dependency>
+			<groupId>com.alibaba.cloud</groupId>
+			<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>mysql</groupId>
+			<artifactId>mysql-connector-java</artifactId>
+			<scope>runtime</scope>
+		</dependency>
+		<dependency>
+			<groupId>com.alibaba</groupId>
+			<artifactId>druid</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.projectlombok</groupId>
+			<artifactId>lombok</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-webmvc</artifactId>
+			<version>5.3.13</version>
+		</dependency>
+
 	</dependencies>
 
 	<build>

+ 2 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/ModelingApplication.java

@@ -2,8 +2,10 @@ package com.fdkankan.modeling;
 
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.ComponentScan;
 
 @SpringBootApplication
+@ComponentScan("*")
 public class ModelingApplication {
 
 	public static void main(String[] args) {

+ 70 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/config/MQProducerConfig.java

@@ -0,0 +1,70 @@
+package com.fdkankan.modeling.config;
+
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.producer.DefaultMQProducer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class MQProducerConfig {
+
+    private static Logger log = LoggerFactory.getLogger(MQProducerConfig.class);
+
+    @Value("${rocketmq.name-srv-addr}")
+    private String nameSrvAddr;
+    @Value("${rocketmq.producer.group.testGrop}")
+    private String producerGroupName;
+    /**
+     * 消息最大大小,默认4M
+     */
+    @Value("${rocketmq.producer.maxMessageSize}")
+    private Integer maxMessageSize;
+    /**
+     * 消息发送超时时间,默认3秒
+     */
+    @Value("${rocketmq.producer.sendMsgTimeout}")
+    private Integer sendMsgTimeout;
+    /**
+     * 消息发送失败重试次数,默认2次
+     */
+    @Value("${rocketmq.producer.retryTimesWhenSendFailed}")
+    private Integer retryTimesWhenSendFailed;
+
+    /**
+     * 初始化向rocketmq发送普通消息的生产者
+     */
+    @Bean("ModelingProducer")
+    public DefaultMQProducer testProducer() throws MQClientException {
+        /*
+         * 一个应用创建一个Producer,由应用来维护此对象,可以设置为全局对象或者单例<br>
+         * 注意:ProducerGroupName需要由应用来保证唯一<br>
+         * ProducerGroup这个概念发送普通的消息时,作用不大,但是发送分布式事务消息时,比较关键,
+         * 因为服务器会回查这个Group下的任意一个Producer
+         */
+        DefaultMQProducer producer = new DefaultMQProducer(producerGroupName);
+        producer.setInstanceName(producerGroupName);
+        producer.setNamesrvAddr(nameSrvAddr);
+        //设置 lnstanceName,当一个 Jvm 需要启动多个 Producer 的时候,通过设置不同的 InstanceName来区分,不设置的话系统使用默认名称“DEFAULT”
+//        producer.setInstanceName(properties.getProducerInstanceName());
+        producer.setVipChannelEnabled(false);
+        //发送消息超时时间,默认3000
+        producer.setSendMsgTimeout(sendMsgTimeout);
+        //发送消息失败重试次数,默认2
+        producer.setRetryTimesWhenSendAsyncFailed(retryTimesWhenSendFailed);
+        //消息最大长度 默认1024*1024*4(4M)
+        producer.setMaxMessageSize(maxMessageSize);
+        /*
+         * Producer对象在使用之前必须要调用start初始化,初始化一次即可<br>
+         * 注意:切记不可以在每次发送消息时,都调用start方法
+         */
+        producer.start();
+        log.info("RocketMq " + this + " Started.");
+        return producer;
+    }
+
+
+
+}

+ 61 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/config/MQReceiverConfig.java

@@ -0,0 +1,61 @@
+package com.fdkankan.modeling.config;
+
+import com.fdkankan.modeling.receiver.BuildSceneReceiver;
+import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
+import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+
+@Component
+public class MQReceiverConfig {
+    private static Logger logger = LoggerFactory.getLogger("programLog");
+
+    @Value("${rocketmq.name-srv-addr}")
+    private String nameSrvAddr;
+
+    @Value("${rocketmq.consumer.testGrop}")
+    private String consumerGroupName;
+
+    @Value("${rocketmq.topic.testGrop}")
+    private String topicName;
+
+    @Value("${rocketmq.tag.testGrop}")
+    private String tagName;
+
+    @Autowired
+    private BuildSceneReceiver buildSceneReceiver;
+
+    @PostConstruct
+    public void CalUserTradeAmountConsumer() throws MQClientException {
+        // Instantiate with specified consumer group name.
+        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(consumerGroupName);
+
+        // Specify name server addresses.
+        consumer.setNamesrvAddr(nameSrvAddr);
+        consumer.setInstanceName(consumerGroupName);
+        //广播
+        consumer.setMessageModel(MessageModel.BROADCASTING);
+        //一次最大消费多少数量消息,与List<MessageExt>数组数量有关,默认为1
+        //  consumer.setConsumeThreadMax(batchMaxSize);
+        //设置Consumer第一次启动是从队列头部开始消费还是队列尾部开始消费
+        //如果非第一次启动,那么按照上次消费的位置继续消费
+        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
+
+        // Subscribe one or more topics to consume.
+        consumer.subscribe(topicName, tagName);
+
+        // Register callback to execute on arrival of messages fetched from brokers.
+        consumer.registerMessageListener(buildSceneReceiver);
+
+        //Launch the consumer instance.
+        consumer.start();
+    }
+
+}

+ 9 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/constants/RedisKey.java

@@ -0,0 +1,9 @@
+package com.fdkankan.modeling.constants;
+
+public class RedisKey {
+
+    public static final String SYSTEM_PREFIX = "4dkankan";
+
+    public static final String SCENE_BUILDING = SYSTEM_PREFIX+":scene:building:";
+
+}

+ 35 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/constants/SysConstants.java

@@ -0,0 +1,35 @@
+package com.fdkankan.modeling.constants;
+
+import com.fdkankan.common.utils.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SysConstants {
+    private static final Logger log = LoggerFactory.getLogger(SysConstants.class);
+
+    public static String hostName;
+    public static int modelTimeOut;
+
+    @Value("${hostName.filePath:/opt/hosts/hosts.txt}")
+    public void setHostName(String filePath){
+        try {
+            SysConstants.hostName = FileUtils.readFile(filePath);
+            log.error("从文件({})中获取服务器名称:{}", filePath,hostName);
+        } catch (Exception e) {
+            log.error("从文件中获取服务器名称失败,文件路径{}", filePath);
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 默认超时时间2天
+     * @param timeOut
+     */
+    @Value("${model.timeOut:48}")
+    public void setModelTimeOut(int timeOut){
+        SysConstants.modelTimeOut = timeOut;
+    }
+}

+ 278 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/entity/Scene.java

@@ -0,0 +1,278 @@
+package com.fdkankan.modeling.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * <p>
+ * 场景表
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+@Getter
+@Setter
+@TableName("t_scene")
+public class Scene implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 场景名称
+     */
+    @TableField("scene_name")
+    private String sceneName;
+
+    /**
+     * 场景描述
+     */
+    @TableField("scene_dec")
+    private String sceneDec;
+
+    /**
+     * 场景的链接地址
+     */
+    @TableField("web_site")
+    private String webSite;
+
+    /**
+     * 场景缩略图
+     */
+    @TableField("thumb")
+    private String thumb;
+
+    /**
+     * 创建时间
+     */
+    @TableField("create_time")
+    private Date createTime;
+
+    /**
+     * 0表示未建好,1表示建好,-1表示出错,-2表示不要在官网上显示
+     */
+    @TableField("status")
+    private Integer status;
+
+    /**
+     * 原始的大场景数据(七牛)
+     */
+    @TableField("data_source")
+    private String dataSource;
+
+    /**
+     * 用户表t_user的id
+     */
+    @TableField("user_id")
+    private Long userId;
+
+    /**
+     * 0表示未付款,1表示付款了,-1表示欠费
+     */
+    @TableField("pay_status")
+    private Integer payStatus;
+
+    /**
+     * 相机主表t_camera的id
+     */
+    @TableField("camera_id")
+    private Long cameraId;
+
+    /**
+     * 手机id
+     */
+    @TableField("phone_id")
+    private String phoneId;
+
+    /**
+     * 大场景序号
+     */
+    @TableField("num")
+    private String num;
+
+    /**
+     * 大场景的密钥
+     */
+    @TableField("scene_key")
+    private String sceneKey;
+
+    /**
+     * 0表示其他,1表示文博,2表示地产,3表示电商,4表示餐饮,5表示家居
+     */
+    @TableField("scene_type")
+    private Integer sceneType;
+
+    /**
+     * 1表示推荐,0表示正常
+     */
+    @TableField("recommend")
+    private Integer recommend;
+
+    /**
+     * 浏览次数
+     */
+    @TableField("view_count")
+    private Integer viewCount;
+
+    /**
+     * 版本
+     */
+    @TableField("version")
+    private Integer version;
+
+    /**
+     * 表示缩略图是否存在
+     */
+    @TableField("thumb_status")
+    private Integer thumbStatus;
+
+    /**
+     * 0表示默认,1表示自己上传
+     */
+    @TableField("floor_logo")
+    private String floorLogo;
+
+    /**
+     * 标记大小
+     */
+    @TableField("floor_logo_size")
+    private Integer floorLogoSize;
+
+    /**
+     * 要上传的热点的id集合,用逗号隔开
+     */
+    @TableField("hots_ids")
+    private String hotsIds;
+
+    /**
+     * 表示初始点信息
+     */
+    @TableField("entry")
+    private String entry;
+
+    /**
+     * 拍摄数量
+     */
+    @TableField("shoot_count")
+    private Integer shootCount;
+
+    /**
+     * 风格
+     */
+    @TableField("style")
+    private Integer style;
+
+    /**
+     * 要gps定位
+     */
+    @TableField("gps")
+    private String gps;
+
+    /**
+     * 方案:1是双目,2是转台,3是六目,4是八目
+     */
+    @TableField("scene_scheme")
+    private Integer sceneScheme;
+
+    /**
+     * 背景音乐名称
+     */
+    @TableField("bg_music")
+    private String bgMusic;
+
+    /**
+     * 记录的状态,A: 生效,I: 禁用
+     */
+    @TableField("rec_status")
+    private String recStatus;
+
+    /**
+     * 更新时间
+     */
+    @TableField("update_time")
+    private Date updateTime;
+
+    /**
+     * 普通录屏文件地址
+     */
+    @TableField("screencap_voice_src")
+    private String screencapVoiceSrc;
+
+    /**
+     * 旧版录屏数据地址
+     */
+    @TableField("screencap_music")
+    private String screencapMusic;
+
+    /**
+     * 录屏文件个数
+     */
+    @TableField("screencap_len")
+    private Integer screencapLen;
+
+    /**
+     * 录音文件地址
+     */
+    @TableField("screencap_voice_sound")
+    private String screencapVoiceSound;
+
+    /**
+     * 选择的类型,sound为screencapVoiceSound,file为screencapVoiceSrc
+     */
+    @TableField("screencap_voice_type")
+    private String screencapVoiceType;
+
+    /**
+     * 录屏文件地址
+     */
+    @TableField("play_data")
+    private String playData;
+
+    /**
+     * 算法类型
+     */
+    @TableField("algorithm")
+    private String algorithm;
+
+    /**
+     * oss服务商
+     */
+    @TableField("oss")
+    private String oss;
+
+    /**
+     * 重新建模的版本
+     */
+    @TableField("floor_edit_ver")
+    private Integer floorEditVer;
+
+    /**
+     * 正式发布重新建模的版本
+     */
+    @TableField("floor_publish_ver")
+    private Integer floorPublishVer;
+
+    /**
+     * 使用容量
+     */
+    @TableField("space")
+    private Long space;
+
+    /**
+     * 录屏图片存放文件
+     */
+    @TableField("screencap_thumb")
+    private String screencapThumb;
+
+
+}

+ 95 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/entity/SceneFileBuild.java

@@ -0,0 +1,95 @@
+package com.fdkankan.modeling.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * <p>
+ * 场景文件建模表
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+@Getter
+@Setter
+@TableName("t_scene_file_build")
+public class SceneFileBuild implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 相机的Mac地址
+     */
+    @TableField("child_name")
+    private String childName;
+
+    /**
+     * 文件id
+     */
+    @TableField("file_id")
+    private String fileId;
+
+    /**
+     * unicode
+     */
+    @TableField("unicode")
+    private String unicode;
+
+    /**
+     * 上传状态,0-上传中,1-上传成功,-1-上传失败
+     */
+    @TableField("upload_status")
+    private Integer uploadStatus;
+
+    /**
+     * 建模状态,0-未建模,1-请求建模,2-等待建模(队列中),3-建模成功,-1-建模失败
+     */
+    @TableField("build_status")
+    private Integer buildStatus;
+
+    /**
+     * 照片总张数
+     */
+    @TableField("total_pic_num")
+    private Integer totalPicNum;
+
+    @TableField("chunks")
+    private Integer chunks;
+
+    /**
+     * 创建时间
+     */
+    @TableField("create_time")
+    private Date createTime;
+
+    /**
+     * 记录的状态,A: 生效,I: 禁用
+     */
+    @TableField("rec_status")
+    private String recStatus;
+
+    /**
+     * 更新时间
+     */
+    @TableField("update_time")
+    private Date updateTime;
+
+    /**
+     * 0-有效,1-删除
+     */
+    @TableField("tb_status")
+    private Integer tbStatus;
+
+
+}

+ 146 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/entity/ScenePro.java

@@ -0,0 +1,146 @@
+package com.fdkankan.modeling.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * <p>
+ * pro场景表
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+@Getter
+@Setter
+@TableName("t_scene_pro")
+public class ScenePro implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 场景名称
+     */
+    @TableField("scene_name")
+    private String sceneName;
+
+    /**
+     * 场景描述
+     */
+    @TableField("scene_dec")
+    private String sceneDec;
+
+    /**
+     * 场景的链接地址
+     */
+    @TableField("web_site")
+    private String webSite;
+
+    /**
+     * 场景缩略图
+     */
+    @TableField("thumb")
+    private String thumb;
+
+    /**
+     * 用户表t_user的id
+     */
+    @TableField("user_id")
+    private Long userId;
+
+    /**
+     * 相机主表t_camera的id
+     */
+    @TableField("camera_id")
+    private Long cameraId;
+
+    /**
+     * 场景logo
+     */
+    @TableField("scene_logo")
+    private String sceneLogo;
+
+    /**
+     * 大场景序号
+     */
+    @TableField("scene_code")
+    private String sceneCode;
+
+    /**
+     * 0-其他,1-文博,2-地产,3-电商,4-餐饮,5-家居,99-一件换装虚拟房源
+     */
+    @TableField("scene_type")
+    private Integer sceneType;
+
+    /**
+     * 浏览次数
+     */
+    @TableField("view_count")
+    private Integer viewCount;
+
+    /**
+     * 拍摄数量
+     */
+    @TableField("shoot_count")
+    private Integer shootCount;
+
+    /**
+     * 点位视频
+     */
+    @TableField("videos")
+    private String videos;
+
+    /**
+     * 要gps定位
+     */
+    @TableField("gps")
+    private String gps;
+
+    /**
+     * 方案:1-双目,2-转台,3-六目,4-八目,10-获取4k图,11-获取2k,12-获取1k
+     */
+    @TableField("scene_scheme")
+    private Integer sceneScheme;
+
+    /**
+     * 记录的状态,A: 生效,I: 禁用
+     */
+    @TableField("rec_status")
+    private String recStatus;
+
+    /**
+     * 算法类型(V2,V3)
+     */
+    @TableField("build_type")
+    private String buildType;
+
+    /**
+     * 创建时间
+     */
+    @TableField("create_time")
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    @TableField("update_time")
+    private Date updateTime;
+
+    /**
+     * 0-有效,1-删除
+     */
+    @TableField("tb_status")
+    private Integer tbStatus;
+
+
+}

+ 176 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/entity/SceneProEdit.java

@@ -0,0 +1,176 @@
+package com.fdkankan.modeling.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * <p>
+ * pro场景编辑数据表
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+@Getter
+@Setter
+@TableName("t_scene_pro_edit")
+public class SceneProEdit implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * pro场景id
+     */
+    @TableField("pro_id")
+    private Long proId;
+
+    /**
+     * 大场景的密钥
+     */
+    @TableField("scene_key")
+    private String sceneKey;
+
+    /**
+     * 展示页面密码,0不需要,1需要
+     */
+    @TableField("need_key")
+    private Integer needKey;
+
+    /**
+     * 版本
+     */
+    @TableField("version")
+    private Integer version;
+
+    /**
+     * 表示缩略图是否存在
+     */
+    @TableField("thumb_status")
+    private Integer thumbStatus;
+
+    /**
+     * 地面点位标志
+     */
+    @TableField("marker_logo")
+    private String markerLogo;
+
+    /**
+     * 0表示默认,1表示自己上传
+     */
+    @TableField("floor_logo")
+    private String floorLogo;
+
+    /**
+     * 标记大小
+     */
+    @TableField("floor_logo_size")
+    private Integer floorLogoSize;
+
+    /**
+     * 要上传的热点的id集合,用逗号隔开
+     */
+    @TableField("hots_ids")
+    private String hotsIds;
+
+    /**
+     * 表示初始点信息
+     */
+    @TableField("entry")
+    private String entry;
+
+    /**
+     * 背景音乐名称
+     */
+    @TableField("bg_music")
+    private String bgMusic;
+
+    /**
+     * 记录的状态,A: 生效,I: 禁用
+     */
+    @TableField("rec_status")
+    private String recStatus;
+
+    /**
+     * 普通录屏文件地址
+     */
+    @TableField("screencap_voice_src")
+    private String screencapVoiceSrc;
+
+    /**
+     * 录音文件地址
+     */
+    @TableField("screencap_voice_sound")
+    private String screencapVoiceSound;
+
+    /**
+     * 同步录音地址
+     */
+    @TableField("screencap_voice_soundsync")
+    private String screencapVoiceSoundsync;
+
+    /**
+     * 选择的类型,sound为screencapVoiceSound,file为screencapVoiceSrc,soundsync为screencap_voice_soundsync
+     */
+    @TableField("screencap_voice_type")
+    private String screencapVoiceType;
+
+    /**
+     * 录屏文件地址
+     */
+    @TableField("play_data")
+    private String playData;
+
+    /**
+     * 重新建模的版本
+     */
+    @TableField("floor_edit_ver")
+    private Integer floorEditVer;
+
+    /**
+     * 正式发布重新建模的版本
+     */
+    @TableField("floor_publish_ver")
+    private Integer floorPublishVer;
+
+    /**
+     * 录屏图片存放文件
+     */
+    @TableField("screencap_thumb")
+    private String screencapThumb;
+
+    /**
+     * 分享的logo和生成二维码的logo
+     */
+    @TableField("share_logo")
+    private String shareLogo;
+
+    /**
+     * 创建时间
+     */
+    @TableField("create_time")
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    @TableField("update_time")
+    private Date updateTime;
+
+    /**
+     * 0-有效,1-删除
+     */
+    @TableField("tb_status")
+    private Integer tbStatus;
+
+
+}

+ 164 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/entity/SceneProEditExt.java

@@ -0,0 +1,164 @@
+package com.fdkankan.modeling.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * <p>
+ * pro场景编辑数据表
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+@Getter
+@Setter
+@TableName("t_scene_pro_edit_ext")
+public class SceneProEditExt implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * pro场景编辑数据表id
+     */
+    @TableField("pro_edit_id")
+    private Long proEditId;
+
+    /**
+     * 小地图浏览
+     */
+    @TableField("map_visi")
+    private Integer mapVisi;
+
+    /**
+     * 自动导览
+     */
+    @TableField("tour_visi")
+    private Integer tourVisi;
+
+    /**
+     * vr模式
+     */
+    @TableField("vr_visi")
+    private Integer vrVisi;
+
+    /**
+     * 展示页面是否显示标尺
+     */
+    @TableField("ruler_visi")
+    private Integer rulerVisi;
+
+    /**
+     * 展示页面cad图在平面图是否显示
+     */
+    @TableField("cad_img_visi")
+    private Integer cadImgVisi;
+
+    /**
+     * cad平面图
+     */
+    @TableField("floor_plan_png")
+    private String floorPlanPng;
+
+    /**
+     * cad平面图参数
+     */
+    @TableField("cad_info")
+    private String cadInfo;
+
+    @TableField("pano_visi")
+    private Integer panoVisi;
+
+    @TableField("m2d_visi")
+    private Integer m2dVisi;
+
+    @TableField("m3d_visi")
+    private Integer m3dVisi;
+
+    @TableField("measure_visi")
+    private Integer measureVisi;
+
+    /**
+     * 肖安需求,场景于场景之间的关联
+     */
+    @TableField("link_scene")
+    private String linkScene;
+
+    @TableField("overlay")
+    private String overlay;
+
+    /**
+     * 是否显示底部logo,1显示,0不显示
+     */
+    @TableField("show_logo_bottom")
+    private Boolean showLogoBottom;
+
+    /**
+     * 全景图版本号
+     */
+    @TableField("images_version")
+    private Integer imagesVersion;
+
+    /**
+     * 上传的背景音乐
+     */
+    @TableField("bg_music_name")
+    private String bgMusicName;
+
+    @TableField("jump_scene")
+    private Boolean jumpScene;
+
+    /**
+     * 旋转角度
+     */
+    @TableField("floor_plan_angle")
+    private String floorPlanAngle;
+
+    /**
+     * 场景下载次数
+     */
+    @TableField("download_num")
+    private Integer downloadNum;
+
+    /**
+     * 绿幕抠图json数据
+     */
+    @TableField("videos_user")
+    private String videosUser;
+
+    /**
+     * 大场景序号(随心装场景码)
+     */
+    @TableField("vr_num")
+    private String vrNum;
+
+    /**
+     * 创建时间
+     */
+    @TableField("create_time")
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    @TableField("update_time")
+    private Date updateTime;
+
+    /**
+     * 0-有效,1-删除
+     */
+    @TableField("tb_status")
+    private Integer tbStatus;
+
+
+}

+ 137 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/entity/SceneProExt.java

@@ -0,0 +1,137 @@
+package com.fdkankan.modeling.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * <p>
+ * pro场景表
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+@Getter
+@Setter
+@TableName("t_scene_pro_ext")
+public class SceneProExt implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 外键id,t_scene_pro_id
+     */
+    @TableField("scene_pro_id")
+    private Long sceneProId;
+
+    /**
+     * 0表示未建好,1表示建好,-1表示出错,-2表示不要在官网上显示
+     */
+    @TableField("scene_status")
+    private Integer sceneStatus;
+
+    /**
+     * 原始的大场景数据(七牛)
+     */
+    @TableField("data_source")
+    private String dataSource;
+
+    /**
+     * 0表示未付款,1表示付款了,-1表示欠费,-2表示容量不足
+     */
+    @TableField("pay_status")
+    private Integer payStatus;
+
+    /**
+     * 手机id
+     */
+    @TableField("phone_id")
+    private String phoneId;
+
+    /**
+     * 1表示推荐,0表示正常
+     */
+    @TableField("recommend")
+    private Integer recommend;
+
+    /**
+     * 所有资源文件名
+     */
+    @TableField("files_name")
+    private String filesName;
+
+    /**
+     * 算法类型
+     */
+    @TableField("algorithm")
+    private String algorithm;
+
+    /**
+     * 服务器的服务商
+     */
+    @TableField("ecs")
+    private String ecs;
+
+    /**
+     * 使用容量
+     */
+    @TableField("space")
+    private Long space;
+
+    /**
+     * 固件版本
+     */
+    @TableField("firmware_version")
+    private String firmwareVersion;
+
+    /**
+     * 计算时间(秒为单位)
+     */
+    @TableField("compute_time")
+    private Long computeTime;
+
+    /**
+     * 场景来源,相机拍摄10以内表示,1表示八目,2双目,3转台,4 激光  其他来源10以上,11:一键换装,12:123看房,13文通虚拟场景
+     */
+    @TableField("scene_source")
+    private Integer sceneSource;
+
+    /**
+     * 大场景序号(随心装场景码)
+     */
+    @TableField("vrnum")
+    private String vrnum;
+
+    @TableField("unicode")
+    private String unicode;
+
+    /**
+     * 创建时间
+     */
+    @TableField("create_time")
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    @TableField("update_time")
+    private Date updateTime;
+
+    /**
+     * 0-有效,1-删除
+     */
+    @TableField("tb_status")
+    private Integer tbStatus;
+
+
+}

+ 144 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/entity/User.java

@@ -0,0 +1,144 @@
+package com.fdkankan.modeling.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * <p>
+ * 用户信息表
+ * </p>
+ *
+ * @author 
+ * @since 2021-12-24
+ */
+@Getter
+@Setter
+@TableName("t_user")
+public class User implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 头像对应的链接地址
+     */
+    @TableField("head")
+    private String head;
+
+    /**
+     * 用户密码
+     */
+    @TableField("password")
+    private String password;
+
+    /**
+     * 用户邮箱
+     */
+    @TableField("email")
+    private String email;
+
+    /**
+     * 注册时间
+     */
+    @TableField("register_time")
+    private Date registerTime;
+
+    /**
+     * 用户名
+     */
+    @TableField("user_name")
+    private String userName;
+
+    /**
+     * 昵称
+     */
+    @TableField("nick_name")
+    private String nickName;
+
+    /**
+     * 0表示禁言(bbs)
+     */
+    @TableField("status")
+    private Integer status;
+
+    /**
+     * 0表示拒绝通知,1表示接受通知
+     */
+    @TableField("is_notice")
+    private Integer isNotice;
+
+    /**
+     * 机构名称
+     */
+    @TableField("organization_name")
+    private String organizationName;
+
+    /**
+     * 主页链接
+     */
+    @TableField("main_page")
+    private String mainPage;
+
+    /**
+     * 所在国家,默认是86
+     */
+    @TableField("country")
+    private String country;
+
+    /**
+     * 所在省份
+     */
+    @TableField("province")
+    private String province;
+
+    /**
+     * 所在城市
+     */
+    @TableField("city")
+    private String city;
+
+    /**
+     * 可下载场景总数
+     */
+    @TableField("download_num_total")
+    private Integer downloadNumTotal;
+
+    /**
+     * 已下载场景总数
+     */
+    @TableField("download_num")
+    private Integer downloadNum;
+
+    /**
+     * 创建时间
+     */
+    @TableField("create_time")
+    private Date createTime;
+
+    /**
+     * 记录的状态,A: 生效,I: 禁用
+     */
+    @TableField("rec_status")
+    @TableLogic(value="A",delval = "I")
+    private String recStatus;
+
+    /**
+     * 更新时间
+     */
+    @TableField("update_time")
+    private Date updateTime;
+
+    /**
+     * 0正常,1删除
+     */
+    @TableField("tb_status")
+    private Integer tbStatus;
+
+
+}

+ 18 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/mapper/ISceneFileBuildMapper.java

@@ -0,0 +1,18 @@
+package com.fdkankan.modeling.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fdkankan.modeling.entity.SceneFileBuild;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 场景文件建模表 Mapper 接口
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+@Mapper
+public interface ISceneFileBuildMapper extends BaseMapper<SceneFileBuild> {
+
+}

+ 18 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/mapper/ISceneMapper.java

@@ -0,0 +1,18 @@
+package com.fdkankan.modeling.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fdkankan.modeling.entity.Scene;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 场景表 Mapper 接口
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+@Mapper
+public interface ISceneMapper extends BaseMapper<Scene> {
+
+}

+ 18 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/mapper/ISceneProEditExtMapper.java

@@ -0,0 +1,18 @@
+package com.fdkankan.modeling.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fdkankan.modeling.entity.SceneProEditExt;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * pro场景编辑数据表 Mapper 接口
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+@Mapper
+public interface ISceneProEditExtMapper extends BaseMapper<SceneProEditExt> {
+
+}

+ 18 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/mapper/ISceneProEditMapper.java

@@ -0,0 +1,18 @@
+package com.fdkankan.modeling.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fdkankan.modeling.entity.SceneProEdit;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * pro场景编辑数据表 Mapper 接口
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+@Mapper
+public interface ISceneProEditMapper extends BaseMapper<SceneProEdit> {
+
+}

+ 18 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/mapper/ISceneProExtMapper.java

@@ -0,0 +1,18 @@
+package com.fdkankan.modeling.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fdkankan.modeling.entity.SceneProExt;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * pro场景表 Mapper 接口
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+@Mapper
+public interface ISceneProExtMapper extends BaseMapper<SceneProExt> {
+
+}

+ 18 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/mapper/ISceneProMapper.java

@@ -0,0 +1,18 @@
+package com.fdkankan.modeling.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fdkankan.modeling.entity.ScenePro;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * pro场景表 Mapper 接口
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+@Mapper
+public interface ISceneProMapper extends BaseMapper<ScenePro> {
+
+}

+ 18 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/mapper/IUserMapper.java

@@ -0,0 +1,18 @@
+package com.fdkankan.modeling.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fdkankan.modeling.entity.User;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 用户信息表 Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2021-12-24
+ */
+@Mapper
+public interface IUserMapper extends BaseMapper<User> {
+
+}

+ 199 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/AndroidNotification.java

@@ -0,0 +1,199 @@
+package com.fdkankan.modeling.push;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+public abstract class AndroidNotification extends UmengNotification {
+	// Keys can be set in the payload level
+	protected static final HashSet<String> PAYLOAD_KEYS = new HashSet<String>(Arrays.asList(new String[]{
+			"display_type"}));
+	
+	// Keys can be set in the body level
+	protected static final HashSet<String> BODY_KEYS = new HashSet<String>(Arrays.asList(new String[]{
+			"ticker", "title", "text", "builder_id", "icon", "largeIcon", "img", "play_vibrate", "play_lights", "play_sound",
+			"sound", "after_open", "url", "activity", "custom"}));
+
+	public enum DisplayType{
+		NOTIFICATION{public String getValue(){return "notification";}},///通知:消息送达到用户设备后,由友盟SDK接管处理并在通知栏上显示通知内容。
+		MESSAGE{public String getValue(){return "message";}};///消息:消息送达到用户设备后,消息内容透传给应用自身进行解析处理。
+		public abstract String getValue();
+	}
+	public enum AfterOpenAction{
+        go_app,//打开应用
+        go_url,//跳转到URL
+        go_activity,//打开特定的activity
+        go_custom//用户自定义内容。
+	}
+	// Set key/value in the rootJson, for the keys can be set please see ROOT_KEYS, PAYLOAD_KEYS, 
+	// BODY_KEYS and POLICY_KEYS.
+	@Override
+	public boolean setPredefinedKeyValue(String key, Object value) throws Exception {
+		if (ROOT_KEYS.contains(key)) {
+			// This key should be in the root level
+			rootJson.put(key, value);
+		} else if (PAYLOAD_KEYS.contains(key)) {
+			// This key should be in the payload level
+			JSONObject payloadJson = null;
+			if (rootJson.containsKey("payload")) {
+				payloadJson = rootJson.getJSONObject("payload");
+			} else {
+				payloadJson = new JSONObject();
+				rootJson.put("payload", payloadJson);
+			}
+			payloadJson.put(key, value);
+		} else if (BODY_KEYS.contains(key)) {
+			// This key should be in the body level
+			JSONObject bodyJson = null;
+			JSONObject payloadJson = null;
+			// 'body' is under 'payload', so build a payload if it doesn't exist
+			if (rootJson.containsKey("payload")) {
+				payloadJson = rootJson.getJSONObject("payload");
+			} else {
+				payloadJson = new JSONObject();
+				rootJson.put("payload", payloadJson);
+			}
+			// Get body JSONObject, generate one if not existed
+			if (payloadJson.containsKey("body")) {
+				bodyJson = payloadJson.getJSONObject("body");
+			} else {
+				bodyJson = new JSONObject();
+				payloadJson.put("body", bodyJson);
+			}
+			bodyJson.put(key, value);
+		} else if (POLICY_KEYS.contains(key)) {
+			// This key should be in the body level
+			JSONObject policyJson = null;
+			if (rootJson.containsKey("policy")) {
+				policyJson = rootJson.getJSONObject("policy");
+			} else {
+				policyJson = new JSONObject();
+				rootJson.put("policy", policyJson);
+			}
+			policyJson.put(key, value);
+		} else {
+			if (key == "payload" || key == "body" || key == "policy" || key == "extra") {
+				throw new Exception("You don't need to set value for " + key + " , just set values for the sub keys in it.");
+			} else {
+				throw new Exception("Unknown key: " + key);
+			}
+		}
+		return true;
+	}
+	
+	// Set extra key/value for Android notification
+	public boolean setExtraField(String key, String value) throws Exception {
+		JSONObject payloadJson = null;
+		JSONObject extraJson = null;
+		if (rootJson.containsKey("payload")) {
+			payloadJson = rootJson.getJSONObject("payload");
+		} else {
+			payloadJson = new JSONObject();
+			rootJson.put("payload", payloadJson);
+		}
+		
+		if (payloadJson.containsKey("extra")) {
+			extraJson = payloadJson.getJSONObject("extra");
+		} else {
+			extraJson = new JSONObject();
+			payloadJson.put("extra", extraJson);
+		}
+		extraJson.put(key, value);
+		return true;
+	}
+	
+	//
+	public void setDisplayType(DisplayType d) throws Exception {
+		setPredefinedKeyValue("display_type", d.getValue());
+	}
+	///通知栏提示文字
+	public void setTicker(String ticker) throws Exception {
+		setPredefinedKeyValue("ticker", ticker);
+	}
+	///通知标题
+	public void setTitle(String title) throws Exception {
+		setPredefinedKeyValue("title", title);
+	}
+	///通知文字描述
+	public void setText(String text) throws Exception {
+		setPredefinedKeyValue("text", text);
+	}
+	///用于标识该通知采用的样式。使用该参数时, 必须在SDK里面实现自定义通知栏样式。
+	public void setBuilderId(Integer builder_id) throws Exception {
+		setPredefinedKeyValue("builder_id", builder_id);
+	}
+	///状态栏图标ID, R.drawable.[smallIcon],如果没有, 默认使用应用图标。
+	public void setIcon(String icon) throws Exception {
+		setPredefinedKeyValue("icon", icon);
+	}
+	///通知栏拉开后左侧图标ID
+	public void setLargeIcon(String largeIcon) throws Exception {
+		setPredefinedKeyValue("largeIcon", largeIcon);
+	}
+	///通知栏大图标的URL链接。该字段的优先级大于largeIcon。该字段要求以http或者https开头。
+	public void setImg(String img) throws Exception {
+		setPredefinedKeyValue("img", img);
+	}
+	///收到通知是否震动,默认为"true"
+	public void setPlayVibrate(Boolean play_vibrate) throws Exception {
+		setPredefinedKeyValue("play_vibrate", play_vibrate.toString());
+	}
+	///收到通知是否闪灯,默认为"true"
+	public void setPlayLights(Boolean play_lights) throws Exception {
+		setPredefinedKeyValue("play_lights", play_lights.toString());
+	}
+	///收到通知是否发出声音,默认为"true"
+	public void setPlaySound(Boolean play_sound) throws Exception {
+		setPredefinedKeyValue("play_sound", play_sound.toString());
+	}
+	///通知声音,R.raw.[sound]. 如果该字段为空,采用SDK默认的声音
+	public void setSound(String sound) throws Exception {
+		setPredefinedKeyValue("sound", sound);
+	}
+	///收到通知后播放指定的声音文件
+	public void setPlaySound(String sound) throws Exception {
+		setPlaySound(true);
+		setSound(sound);
+	}
+	
+	///点击"通知"的后续行为,默认为打开app。
+	public void goAppAfterOpen() throws Exception {
+		setAfterOpenAction(AfterOpenAction.go_app);
+	}
+	public void goUrlAfterOpen(String url) throws Exception {
+		setAfterOpenAction(AfterOpenAction.go_url);
+		setUrl(url);
+	}
+	public void goActivityAfterOpen(String activity) throws Exception {
+		setAfterOpenAction(AfterOpenAction.go_activity);
+		setActivity(activity);
+	}
+	public void goCustomAfterOpen(String custom) throws Exception {
+		setAfterOpenAction(AfterOpenAction.go_custom);
+		setCustomField(custom);
+	}
+	public void goCustomAfterOpen(JSONObject custom) throws Exception {
+		setAfterOpenAction(AfterOpenAction.go_custom);
+		setCustomField(custom);
+	}
+	
+	///点击"通知"的后续行为,默认为打开app。原始接口
+	public void setAfterOpenAction(AfterOpenAction action) throws Exception {
+		setPredefinedKeyValue("after_open", action.toString());
+	}
+	public void setUrl(String url) throws Exception {
+		setPredefinedKeyValue("url", url);
+	}
+	public void setActivity(String activity) throws Exception {
+		setPredefinedKeyValue("activity", activity);
+	}
+	///can be a string of json
+	public void setCustomField(String custom) throws Exception {
+		setPredefinedKeyValue("custom", custom);
+	}
+	public void setCustomField(JSONObject custom) throws Exception {
+		setPredefinedKeyValue("custom", custom);
+	}
+	
+}

+ 6 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/App.java

@@ -0,0 +1,6 @@
+package com.fdkankan.modeling.push;
+
+
+public class App {
+
+}

+ 95 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/IOSNotification.java

@@ -0,0 +1,95 @@
+package com.fdkankan.modeling.push;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+public abstract class IOSNotification extends UmengNotification {
+
+	// Keys can be set in the aps level
+	protected static final HashSet<String> APS_KEYS = new HashSet<String>(Arrays.asList(new String[]{
+			"alert", "badge", "sound", "content-available", "url", "mutable-content"
+	}));
+	
+	@Override
+	public boolean setPredefinedKeyValue(String key, Object value) throws Exception {
+		if (ROOT_KEYS.contains(key)) {
+			// This key should be in the root level
+			rootJson.put(key, value);
+		} else if (APS_KEYS.contains(key)) {
+			// This key should be in the aps level
+			JSONObject apsJson = null;
+			JSONObject payloadJson = null;
+			if (rootJson.containsKey("payload")) {
+				payloadJson = rootJson.getJSONObject("payload");
+			} else {
+				payloadJson = new JSONObject();
+				rootJson.put("payload", payloadJson);
+			}
+			if (payloadJson.containsKey("aps")) {
+				apsJson = payloadJson.getJSONObject("aps");
+			} else {
+				apsJson = new JSONObject();
+				payloadJson.put("aps", apsJson);
+			}
+			apsJson.put(key, value);
+		} else if (POLICY_KEYS.contains(key)) {
+			// This key should be in the body level
+			JSONObject policyJson = null;
+			if (rootJson.containsKey("policy")) {
+				policyJson = rootJson.getJSONObject("policy");
+			} else {
+				policyJson = new JSONObject();
+				rootJson.put("policy", policyJson);
+			}
+			policyJson.put(key, value);
+		} else {
+			if (key == "payload" || key == "aps" || key == "policy") {
+				throw new Exception("You don't need to set value for " + key + " , just set values for the sub keys in it.");
+			} else {
+				throw new Exception("Unknownd key: " + key);
+			}
+		}
+		
+		return true;
+	}
+	// Set customized key/value for IOS notification
+	public boolean setCustomizedField(String key, String value) throws Exception {
+		//rootJson.put(key, value);
+		JSONObject payloadJson = null;
+		if (rootJson.containsKey("payload")) {
+			payloadJson = rootJson.getJSONObject("payload");
+		} else {
+			payloadJson = new JSONObject();
+			rootJson.put("payload", payloadJson);
+		}
+		payloadJson.put(key, value);
+		return true;
+	}
+
+	public void setAlert(String token) throws Exception {
+    	setPredefinedKeyValue("alert", token);
+    }
+
+    public void setAlert(String title ,String subtitle , String body, String url) throws Exception{
+		JSONObject object = new JSONObject();
+		object.put("title" , title);
+		object.put("subtitle" , subtitle);
+		object.put("body" , body);
+		setPredefinedKeyValue("alert",object );
+		setPredefinedKeyValue("url", url);
+		setPredefinedKeyValue("mutable-content", 1);
+	}
+	public void setBadge(Integer badge) throws Exception {
+    	setPredefinedKeyValue("badge", badge);
+    }
+	
+	public void setSound(String sound) throws Exception {
+    	setPredefinedKeyValue("sound", sound);
+    }
+	
+	public void setContentAvailable(Integer contentAvailable) throws Exception {
+    	setPredefinedKeyValue("content-available", contentAvailable);
+    }
+}

+ 103 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/PushClient.java

@@ -0,0 +1,103 @@
+package com.fdkankan.modeling.push;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+@Slf4j
+public class PushClient {
+	
+	// The user agent
+	protected final String USER_AGENT = "Mozilla/5.0";
+
+	// This object is used for sending the post request to Umeng
+	protected HttpClient client = new DefaultHttpClient();
+	
+	// The host
+	protected static final String host = "http://msg.umeng.com";
+	
+	// The upload path
+	protected static final String uploadPath = "/upload";
+	
+	// The post path
+	protected static final String postPath = "/api/send";
+
+	public boolean send(UmengNotification msg) throws Exception {
+		String timestamp = Integer.toString((int)(System.currentTimeMillis() / 1000));
+		msg.setPredefinedKeyValue("timestamp", timestamp);
+        String url = host + postPath;
+        String postBody = msg.getPostBody();
+        String sign = DigestUtils.md5Hex(("POST" + url + postBody + msg.getAppMasterSecret()).getBytes("utf8"));
+        url = url + "?sign=" + sign;
+        HttpPost post = new HttpPost(url);
+        post.setHeader("User-Agent", USER_AGENT);
+        StringEntity se = new StringEntity(postBody, "UTF-8");
+        post.setEntity(se);
+        // Send the post request and get the response
+        HttpResponse response = client.execute(post);
+        int status = response.getStatusLine().getStatusCode();
+        log.info("Response Code : " + status);
+        BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
+        StringBuffer result = new StringBuffer();
+        String line = "";
+        while ((line = rd.readLine()) != null) {
+            result.append(line);
+        }
+        log.info(result.toString());
+        if (status == 200) {
+            log.info("Notification sent successfully.");
+        } else {
+            log.info("Failed to send the notification!");
+        }
+        return true;
+    }
+
+	// Upload file with device_tokens to Umeng
+	public String uploadContents(String appkey,String appMasterSecret,String contents) throws Exception {
+		// Construct the json string
+		JSONObject uploadJson = new JSONObject();
+		uploadJson.put("appkey", appkey);
+		String timestamp = Integer.toString((int)(System.currentTimeMillis() / 1000));
+		uploadJson.put("timestamp", timestamp);
+		uploadJson.put("content", contents);
+		// Construct the request
+		String url = host + uploadPath;
+		String postBody = uploadJson.toString();
+		String sign = DigestUtils.md5Hex(("POST" + url + postBody + appMasterSecret).getBytes("utf8"));
+		url = url + "?sign=" + sign;
+		HttpPost post = new HttpPost(url);
+		post.setHeader("User-Agent", USER_AGENT);
+		StringEntity se = new StringEntity(postBody, "UTF-8");
+		post.setEntity(se);
+		// Send the post request and get the response
+		HttpResponse response = client.execute(post);
+		log.info("Response Code : " + response.getStatusLine().getStatusCode());
+		BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
+		StringBuffer result = new StringBuffer();
+		String line = "";
+		while ((line = rd.readLine()) != null) {
+			result.append(line);
+		}
+		log.info(result.toString());
+		// Decode response string and get file_id from it
+		JSONObject respJson = JSONObject.parseObject(result.toString());
+		String ret = respJson.getString("ret");
+		if (!ret.equals("SUCCESS")) {
+			throw new Exception("Failed to upload file");
+		}
+		JSONObject data = respJson.getJSONObject("data");
+		String fileId = data.getString("file_id");
+		// Set file_id into rootJson using setPredefinedKeyValue
+		
+		return fileId;
+	}
+
+}

+ 331 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/PushMessageConfig.java

@@ -0,0 +1,331 @@
+package com.fdkankan.modeling.push;
+
+
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.modeling.push.android.*;
+import com.fdkankan.modeling.push.ios.*;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Date;
+
+@Slf4j
+public class PushMessageConfig {
+	private String appkey = null;
+	private String appMasterSecret = null;
+	private String timestamp = null;
+	private PushClient client = new PushClient();
+
+	public static final String ANDROID_KEY = "5ee71c03dbc2ec076dd488cb";
+	public static final String ANDROID_SECRET = "gzw4r8frbhq6eigxrvgjkdrm7wgtu83g";
+	public static final String IOS_KEY = "5ee71ca9978eea081640f22a";
+	public static final String IOS_SECRET = "tpuhyojch16pcha2qmpidlbnzkielv9w";
+
+	//转台双目使用
+	public static final String ANDROID_KEY_Z = "60efd777a6f90557b7b97c25";
+	public static final String ANDROID_SECRET_Z = "ll85ov3qzeuas0ig7cw0v5bgzq1bdl07";
+	public static final String IOS_KEY_Z = "60efd7c9a6f90557b7b97d10";
+	public static final String IOS_SECRET_Z = "li62b5f3d9kn8idvy6qva3c5gyidmqwl";
+
+	public PushMessageConfig(String key, String secret) {
+		try {
+			appkey = key;
+			appMasterSecret = secret;
+		} catch (Exception e) {
+			e.printStackTrace();
+			System.exit(1);
+		}
+	}
+	
+	public void sendAndroidBroadcast() throws Exception {
+		AndroidBroadcast broadcast = new AndroidBroadcast(appkey,appMasterSecret);
+		broadcast.setTicker( "Android broadcast ticker");
+		broadcast.setTitle(  "中文的title");
+		broadcast.setText(   "Android broadcast text");
+		broadcast.goAppAfterOpen();
+		broadcast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		// TODO Set 'production_mode' to 'false' if it's a test device. 
+		// For how to register a test device, please see the developer doc.
+		broadcast.setProductionMode();
+		// Set customized fields
+		broadcast.setExtraField("test", "helloworld");
+		//厂商通道相关参数
+		broadcast.setChannelActivity("your channel activity");
+		broadcast.setChannelProperties("abc");
+		client.send(broadcast);
+	}
+	
+	public void sendAndroidUnicast(String token, String ticker, String title, String text, String url) throws Exception {
+		AndroidUnicast unicast = new AndroidUnicast(appkey,appMasterSecret);
+		// TODO Set your device token
+		unicast.setDeviceToken(token);
+		unicast.setTicker(ticker);
+		unicast.setTitle(title);
+		unicast.setText(text);
+		unicast.goUrlAfterOpen(url);
+		unicast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		// TODO Set 'production_mode' to 'false' if it's a test device. 
+		// For how to register a test device, please see the developer doc.
+		unicast.setProductionMode();
+		// Set customized fields
+		unicast.setExtraField("test", "helloworld");
+		unicast.setChannelActivity("com.fdage.eight.module.EightPushMsgHandlerActivity");
+//		unicast.setChannelProperties("abc");
+
+		client.send(unicast);
+	}
+
+	//转台相机
+	public void sendAndroidUnicast2(String token, String ticker, String title, String text, String url) throws Exception {
+		AndroidUnicast unicast = new AndroidUnicast(appkey,appMasterSecret);
+		// TODO Set your device token
+		unicast.setDeviceToken(token);
+		unicast.setTicker(ticker);
+		unicast.setTitle(title);
+		unicast.setText(text);
+		unicast.goUrlAfterOpen(url);
+		unicast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		// TODO Set 'production_mode' to 'false' if it's a test device.
+		// For how to register a test device, please see the developer doc.
+		unicast.setProductionMode();
+		// Set customized fields
+		unicast.setExtraField("test", "helloworld");
+		unicast.setChannelActivity("io.github.zileyuan.umeng_analytics_push.OfflineNotifyClickActivity");
+//		unicast.setChannelProperties("abc");
+
+		client.send(unicast);
+	}
+	
+	public void sendAndroidGroupcast() throws Exception {
+		AndroidGroupcast groupcast = new AndroidGroupcast(appkey,appMasterSecret);
+		/*  TODO
+		 *  Construct the filter condition:
+		 *  "where": 
+		 *	{
+    	 *		"and": 
+    	 *		[
+      	 *			{"tag":"test"},
+      	 *			{"tag":"Test"}
+    	 *		]
+		 *	}
+		 */
+		JSONObject filterJson = new JSONObject();
+		JSONObject whereJson = new JSONObject();
+		JSONArray tagArray = new JSONArray();
+		JSONObject testTag = new JSONObject();
+		JSONObject TestTag = new JSONObject();
+		testTag.put("tag", "test");
+		TestTag.put("tag", "Test");
+		tagArray.add(testTag);
+		tagArray.add(TestTag);
+		whereJson.put("and", tagArray);
+		filterJson.put("where", whereJson);
+
+		groupcast.setFilter(filterJson);
+		groupcast.setTicker( "Android groupcast ticker");
+		groupcast.setTitle(  "中文的title");
+		groupcast.setText(   "Android groupcast text");
+		groupcast.goAppAfterOpen();
+		groupcast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		groupcast.setChannelActivity("your channel activity");
+		// TODO Set 'production_mode' to 'false' if it's a test device. 
+		// For how to register a test device, please see the developer doc.
+		groupcast.setProductionMode();
+		//厂商通道相关参数
+		groupcast.setChannelActivity("your channel activity");
+		groupcast.setChannelProperties("abc");
+		client.send(groupcast);
+	}
+	
+	public void sendAndroidCustomizedcast() throws Exception {
+		AndroidCustomizedcast customizedcast = new AndroidCustomizedcast(appkey,appMasterSecret);
+		// TODO Set your alias here, and use comma to split them if there are multiple alias.
+		// And if you have many alias, you can also upload a file containing these alias, then 
+		// use file_id to send customized notification.
+		customizedcast.setAlias("alias", "alias_type");
+		customizedcast.setTicker( "Android customizedcast ticker");
+		customizedcast.setTitle(  "中文的title");
+		customizedcast.setText(   "Android customizedcast text");
+		customizedcast.goAppAfterOpen();
+		customizedcast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		// TODO Set 'production_mode' to 'false' if it's a test device. 
+		// For how to register a test device, please see the developer doc.
+		customizedcast.setProductionMode();
+		//厂商通道相关参数
+		customizedcast.setChannelActivity("your channel activity");
+		customizedcast.setChannelProperties("abc");
+		client.send(customizedcast);
+	}
+	
+	public void sendAndroidCustomizedcastFile() throws Exception {
+		AndroidCustomizedcast customizedcast = new AndroidCustomizedcast(appkey,appMasterSecret);
+		// TODO Set your alias here, and use comma to split them if there are multiple alias.
+		// And if you have many alias, you can also upload a file containing these alias, then 
+		// use file_id to send customized notification.
+		String fileId = client.uploadContents(appkey,appMasterSecret,"aa"+"\n"+"bb"+"\n"+"alias");
+		customizedcast.setFileId(fileId, "alias_type");
+		customizedcast.setTicker( "Android customizedcast ticker");
+		customizedcast.setTitle(  "中文的title");
+		customizedcast.setText(   "Android customizedcast text");
+		customizedcast.goAppAfterOpen();
+		customizedcast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		// TODO Set 'production_mode' to 'false' if it's a test device. 
+		// For how to register a test device, please see the developer doc.
+		customizedcast.setProductionMode();
+		//厂商通道相关参数
+		customizedcast.setChannelActivity("your channel activity");
+		customizedcast.setChannelProperties("abc");
+		client.send(customizedcast);
+	}
+	
+	public void sendAndroidFilecast() throws Exception {
+		AndroidFilecast filecast = new AndroidFilecast(appkey,appMasterSecret);
+		// TODO upload your device tokens, and use '\n' to split them if there are multiple tokens 
+		String fileId = client.uploadContents(appkey,appMasterSecret,"aa"+"\n"+"bb");
+		filecast.setFileId( fileId);
+		filecast.setTicker( "Android filecast ticker");
+		filecast.setTitle(  "中文的title");
+		filecast.setText(   "Android filecast text");
+		filecast.goAppAfterOpen();
+		filecast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		//厂商通道相关参数
+		filecast.setChannelActivity("your channel activity");
+		filecast.setChannelProperties("abc");
+		client.send(filecast);
+	}
+	
+	public void sendIOSBroadcast() throws Exception {
+		IOSBroadcast broadcast = new IOSBroadcast(appkey,appMasterSecret);
+        //alert值设置为字符串
+		//broadcast.setAlert("IOS 广播测试");
+		//alert的值设置为字典
+//		broadcast.setAlert("今日天气" , "" , "今日可能下雨🌂");
+		broadcast.setBadge( 0);
+		broadcast.setSound( "default");
+		// TODO set 'production_mode' to 'true' if your app is under production mode
+		broadcast.setTestMode();
+		// Set customized fields
+		broadcast.setCustomizedField("test", "helloworld");
+		client.send(broadcast);
+	}
+	
+	public void sendIOSUnicast(String token, String title ,String subtitle , String body, String url) throws Exception {
+		IOSUnicast unicast = new IOSUnicast(appkey,appMasterSecret);
+		// TODO Set your device token
+		unicast.setDeviceToken(token);
+		//alert值设置为字符串
+		//unicast.setAlert("IOS 单播测试");
+		//alert的值设置为字典
+		unicast.setAlert(title, subtitle, body, url);
+//		unicast.setBadge( 0);
+		unicast.setSound( "default");
+		// TODO set 'production_mode' to 'true' if your app is under production mode
+		unicast.setProductionMode();
+//		unicast.setTestMode();
+		unicast.setDescription(title);
+		unicast.setExpireTime(DateUtil.formatTime(DateUtil.offsetDay(new Date(), 1)));
+		// Set customized fields
+//		unicast.setCustomizedField("url", url);
+		client.send(unicast);
+	}
+
+	
+	public void sendIOSGroupcast() throws Exception {
+		IOSGroupcast groupcast = new IOSGroupcast(appkey,appMasterSecret);
+		/*  TODO
+		 *  Construct the filter condition:
+		 *  "where": 
+		 *	{
+    	 *		"and": 
+    	 *		[
+      	 *			{"tag":"iostest"}
+    	 *		]
+		 *	}
+		 */
+		JSONObject filterJson = new JSONObject();
+		JSONObject whereJson = new JSONObject();
+		JSONArray tagArray = new JSONArray();
+		JSONObject testTag = new JSONObject();
+		testTag.put("tag", "iostest");
+		tagArray.add(testTag);
+		whereJson.put("and", tagArray);
+		filterJson.put("where", whereJson);
+		log.info(filterJson.toString());
+		
+		// Set filter condition into rootJson
+		groupcast.setFilter(filterJson);
+		//groupcast.setAlert("IOS 组播测试");
+		//alert的值设置为字典
+//		groupcast.setAlert("今日天气" , "subtitle" , "今日可能下雨🌂");
+		groupcast.setBadge( 0);
+		groupcast.setSound( "default");
+		// TODO set 'production_mode' to 'true' if your app is under production mode
+		groupcast.setTestMode();
+		client.send(groupcast);
+	}
+	
+	public void sendIOSCustomizedcast() throws Exception {
+		IOSCustomizedcast customizedcast = new IOSCustomizedcast(appkey,appMasterSecret);
+		// TODO Set your alias and alias_type here, and use comma to split them if there are multiple alias.
+		// And if you have many alias, you can also upload a file containing these alias, then 
+		// use file_id to send customized notification.
+		customizedcast.setAlias("alias", "alias_type");
+		//customizedcast.setAlert("IOS 个性化测试");
+		//alert的值设置为字典
+//		customizedcast.setAlert("今日天气" , "" , "今日可能下雨🌂");
+		customizedcast.setBadge( 0);
+		customizedcast.setSound( "default");
+		// TODO set 'production_mode' to 'true' if your app is under production mode
+		customizedcast.setTestMode();
+		client.send(customizedcast);
+	}
+	
+	public void sendIOSFilecast() throws Exception {
+		IOSFilecast filecast = new IOSFilecast(appkey,appMasterSecret);
+		// TODO upload your device tokens, and use '\n' to split them if there are multiple tokens 
+		String fileId = client.uploadContents(appkey,appMasterSecret,"aa"+"\n"+"bb");
+		filecast.setFileId( fileId);
+		//filecast.setAlert("IOS 文件播测试");
+		//alert的值设置为字典
+//		filecast.setAlert("今日天气" , "" , "今日可能下雨🌂");
+		filecast.setBadge( 0);
+		filecast.setSound( "default");
+		// TODO set 'production_mode' to 'true' if your app is under production mode
+		filecast.setTestMode();
+		client.send(filecast);
+	}
+	
+	public static void main(String[] args) {
+		// TODO set your appkey and master secret here
+		//安卓
+//		Demo demo = new Demo(ANDROID_KEY, ANDROID_SECRET);
+		//ios
+		PushMessageConfig pushMessageConfig = new PushMessageConfig(IOS_KEY, IOS_SECRET);
+		try {
+//			demo.sendAndroidUnicast("AneqkEZahjbW3cF7gu8juNYqz54ZFfK7kjMpTOiQL9dl",
+//					"测试项目计算完成", "四维看看Pro", "您上传的测试项目计算完成,点击查看",
+//					"https://test.4dkankan.com/smobile.html?m=t-e9uHHdn");
+			pushMessageConfig.sendIOSUnicast("ec61a2aa52673c96c12024e07ce267e391ca560e0c60f15ee09e65c8843ef7f4",
+					"四维看看Pro", "测试项目计算完成", "您上传的测试项目计算完成,点击查看",
+					"https://test.4dkankan.com/smobile.html?m=t-e9uHHdn");
+			/* TODO these methods are all available, just fill in some fields and do the test
+			 * demo.sendAndroidCustomizedcastFile();
+			 * demo.sendAndroidBroadcast();
+			 * demo.sendAndroidGroupcast();
+			 * demo.sendAndroidCustomizedcast();
+			 * demo.sendAndroidFilecast();
+			 * 
+			 * demo.sendIOSBroadcast();
+			 * demo.sendIOSUnicast();
+			 * demo.sendIOSGroupcast();
+			 * demo.sendIOSCustomizedcast();
+			 * demo.sendIOSFilecast();
+			 */
+		} catch (Exception ex) {
+			ex.printStackTrace();
+		}
+	}
+	
+
+}

+ 86 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/UmengNotification.java

@@ -0,0 +1,86 @@
+package com.fdkankan.modeling.push;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+public abstract class UmengNotification {
+	// This JSONObject is used for constructing the whole request string.
+	protected final JSONObject rootJson = new JSONObject();
+	
+	
+	// The app master secret
+	protected String appMasterSecret;
+	
+	// Keys can be set in the root level
+	protected static final HashSet<String> ROOT_KEYS = new HashSet<String>(Arrays.asList(new String[]{
+			"appkey", "timestamp", "type", "device_tokens", "alias", "alias_type", "file_id", 
+			"filter", "production_mode", "feedback", "description", "thirdparty_id" , "mipush" , "mi_activity" , "channel_properties"}));
+	
+	// Keys can be set in the policy level
+	protected static final HashSet<String> POLICY_KEYS = new HashSet<String>(Arrays.asList(new String[]{
+			"start_time", "expire_time", "max_send_num"
+	}));
+	
+	// Set predefined keys in the rootJson, for extra keys(Android) or customized keys(IOS) please 
+	// refer to corresponding methods in the subclass.
+	public abstract boolean setPredefinedKeyValue(String key, Object value) throws Exception;
+	public void setAppMasterSecret(String secret) {
+		appMasterSecret = secret;
+	}
+	
+	public String getPostBody(){
+		return rootJson.toString();
+	}
+	
+	protected final String getAppMasterSecret(){
+		return appMasterSecret;
+	}
+	
+	protected void setProductionMode(Boolean prod) throws Exception {
+    	setPredefinedKeyValue("production_mode", prod.toString());
+    }
+
+	///正式模式
+    public void setProductionMode() throws Exception {
+    	setProductionMode(true);
+    }
+
+    ///测试模式
+    public void setTestMode() throws Exception {
+    	setProductionMode(false);
+    }
+
+    ///发送消息描述,建议填写。
+    public void setDescription(String description) throws Exception {
+    	setPredefinedKeyValue("description", description);
+    }
+
+    ///定时发送时间,若不填写表示立即发送。格式: "YYYY-MM-DD hh:mm:ss"。
+    public void setStartTime(String startTime) throws Exception {
+    	setPredefinedKeyValue("start_time", startTime);
+    }
+    ///消息过期时间,格式: "YYYY-MM-DD hh:mm:ss"。
+    public void setExpireTime(String expireTime) throws Exception {
+    	setPredefinedKeyValue("expire_time", expireTime);
+    }
+    ///发送限速,每秒发送的最大条数。
+    public void setMaxSendNum(Integer num) throws Exception {
+    	setPredefinedKeyValue("max_send_num", num);
+    }
+
+    //厂商弹窗activity
+	public void setChannelActivity(String activity) throws Exception{
+       setPredefinedKeyValue("mipush", "true");
+       setPredefinedKeyValue("mi_activity",activity );
+	}
+
+	//厂商属性配置
+	public void setChannelProperties(String xiaoMiChannelId) throws Exception{
+		JSONObject object = new JSONObject();
+		object.put("xiaomi_channel_id" , xiaoMiChannelId);
+		setPredefinedKeyValue("channel_properties", object);
+	}
+
+}

+ 11 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/android/AndroidBroadcast.java

@@ -0,0 +1,11 @@
+package com.fdkankan.modeling.push.android;
+
+import com.fdkankan.modeling.push.AndroidNotification;
+
+public class AndroidBroadcast extends AndroidNotification {
+	public AndroidBroadcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "broadcast");	
+	}
+}

+ 22 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/android/AndroidCustomizedcast.java

@@ -0,0 +1,22 @@
+package com.fdkankan.modeling.push.android;
+
+import com.fdkankan.modeling.push.AndroidNotification;
+
+public class AndroidCustomizedcast extends AndroidNotification {
+	public AndroidCustomizedcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "customizedcast");	
+	}
+	
+	public void setAlias(String alias,String aliasType) throws Exception {
+    	setPredefinedKeyValue("alias", alias);
+    	setPredefinedKeyValue("alias_type", aliasType);
+    }
+			
+	public void setFileId(String fileId,String aliasType) throws Exception {
+    	setPredefinedKeyValue("file_id", fileId);
+    	setPredefinedKeyValue("alias_type", aliasType);
+    }
+
+}

+ 15 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/android/AndroidFilecast.java

@@ -0,0 +1,15 @@
+package com.fdkankan.modeling.push.android;
+
+import com.fdkankan.modeling.push.AndroidNotification;
+
+public class AndroidFilecast extends AndroidNotification {
+	public AndroidFilecast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "filecast");	
+	}
+	
+	public void setFileId(String fileId) throws Exception {
+    	setPredefinedKeyValue("file_id", fileId);
+    }
+}

+ 16 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/android/AndroidGroupcast.java

@@ -0,0 +1,16 @@
+package com.fdkankan.modeling.push.android;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.modeling.push.AndroidNotification;
+
+public class AndroidGroupcast extends AndroidNotification {
+	public AndroidGroupcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "groupcast");	
+	}
+	
+	public void setFilter(JSONObject filter) throws Exception {
+    	setPredefinedKeyValue("filter", filter);
+    }
+}

+ 16 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/android/AndroidUnicast.java

@@ -0,0 +1,16 @@
+package com.fdkankan.modeling.push.android;
+
+import com.fdkankan.modeling.push.AndroidNotification;
+
+public class AndroidUnicast extends AndroidNotification {
+	public AndroidUnicast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "unicast");	
+	}
+	
+	public void setDeviceToken(String token) throws Exception {
+    	setPredefinedKeyValue("device_tokens", token);
+    }
+
+}

+ 12 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/ios/IOSBroadcast.java

@@ -0,0 +1,12 @@
+package com.fdkankan.modeling.push.ios;
+
+import com.fdkankan.modeling.push.IOSNotification;
+
+public class IOSBroadcast extends IOSNotification {
+	public IOSBroadcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "broadcast");	
+		
+	}
+}

+ 23 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/ios/IOSCustomizedcast.java

@@ -0,0 +1,23 @@
+package com.fdkankan.modeling.push.ios;
+
+
+import com.fdkankan.modeling.push.IOSNotification;
+
+public class IOSCustomizedcast extends IOSNotification {
+	public IOSCustomizedcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "customizedcast");	
+	}
+	
+	public void setAlias(String alias,String aliasType) throws Exception {
+    	setPredefinedKeyValue("alias", alias);
+    	setPredefinedKeyValue("alias_type", aliasType);
+    }
+		
+	public void setFileId(String fileId, String aliasType) throws Exception {
+		setPredefinedKeyValue("file_id", fileId);
+		setPredefinedKeyValue("alias_type", aliasType);
+	}
+
+}

+ 15 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/ios/IOSFilecast.java

@@ -0,0 +1,15 @@
+package com.fdkankan.modeling.push.ios;
+
+import com.fdkankan.modeling.push.IOSNotification;
+
+public class IOSFilecast extends IOSNotification {
+	public IOSFilecast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "filecast");	
+	}
+	
+	public void setFileId(String fileId) throws Exception {
+    	setPredefinedKeyValue("file_id", fileId);
+    }
+}

+ 16 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/ios/IOSGroupcast.java

@@ -0,0 +1,16 @@
+package com.fdkankan.modeling.push.ios;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.modeling.push.IOSNotification;
+
+public class IOSGroupcast extends IOSNotification {
+	public IOSGroupcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "groupcast");	
+	}
+	
+	public void setFilter(JSONObject filter) throws Exception {
+    	setPredefinedKeyValue("filter", filter);
+    }
+}

+ 15 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/push/ios/IOSUnicast.java

@@ -0,0 +1,15 @@
+package com.fdkankan.modeling.push.ios;
+
+import com.fdkankan.modeling.push.IOSNotification;
+
+public class IOSUnicast extends IOSNotification {
+	public IOSUnicast(String appkey,String appMasterSecret) throws Exception{
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "unicast");	
+	}
+	
+	public void setDeviceToken(String token) throws Exception {
+    	setPredefinedKeyValue("device_tokens", token);
+    }
+}

+ 842 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/receiver/BuildSceneReceiver.java

@@ -0,0 +1,842 @@
+package com.fdkankan.modeling.receiver;
+
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.common.constant.ConstantFilePath;
+import com.fdkankan.common.constant.ConstantUrl;
+import com.fdkankan.common.utils.CreateObjUtil;
+import com.fdkankan.common.utils.FileUtil;
+import com.fdkankan.common.utils.FileUtils;
+import com.fdkankan.modeling.constants.RedisKey;
+import com.fdkankan.modeling.constants.SysConstants;
+import com.fdkankan.modeling.entity.*;
+import com.fdkankan.modeling.push.PushMessageConfig;
+import com.fdkankan.modeling.service.*;
+import com.fdkankan.modeling.utils.ComputerUtil;
+import com.fdkankan.modeling.utils.DingDingUtils;
+import com.fdkankan.modeling.utils.PushMsgUtil;
+import com.taobao.api.ApiException;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
+import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
+import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
+import org.apache.rocketmq.client.producer.DefaultMQProducer;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.client.RestTemplate;
+import com.fdkankan.utils.UploadUtils;
+
+import java.io.*;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.time.Duration;
+import java.time.temporal.ChronoUnit;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.*;
+
+import static com.fdkankan.modeling.push.PushMessageConfig.*;
+
+
+@Log4j2
+@Component
+@ConditionalOnProperty(name = "rabbitmq.queue.enable",havingValue = "true")
+public class BuildSceneReceiver implements MessageListenerConcurrently {
+
+    @Autowired
+    private ISceneService sceneService;
+    @Autowired
+    private ISceneProService sceneProService;
+    @Autowired
+    private IUserService userService;
+    @Autowired
+    private ISceneFileBuildService sceneFileBuildService;
+
+    @Autowired
+    private ISceneProEditService sceneProEditService;
+
+
+    @Autowired
+    private ISceneProEditExtService sceneProEditExtService;
+
+    @Autowired
+    private ISceneProExtService sceneProExtService;
+
+    @Autowired
+    private RedisTemplate<String,String> redisTemplate;
+
+    private RestTemplate restTemplate = new RestTemplate();
+
+    @Value("${main.url}")
+    private String mainUrl;
+
+    @Value("${4dkk.laserService.host}")
+    private String laserHost;
+
+    @Value("${oss.type}")
+    private String ossType;
+
+    @Value("${oss.url.prefix}")
+    private String prefixAli;
+
+    @Value("${scene.pro.mobile.show.url}")
+    private String sceneProNewUrl;
+
+    @Autowired
+    private DefaultMQProducer mqProducer;
+
+    @Autowired
+    private UploadUtils uploadUtils;
+
+    @Override
+    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgExt,
+                                                    ConsumeConcurrentlyContext consumeConcurrentlyContext) {
+        if (CollectionUtils.isEmpty(msgExt)) {
+            log.error("消息内容为空,退出构建,当前服务器id:{}", SysConstants.hostName);
+            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
+        }
+        MessageExt messageExt = msgExt.get(0);
+        Object object = JSON.parse(messageExt.getBody());
+        String msg = JSON.toJSONString(object);
+        log.info("开始处理消息,消息队列:{},消息内容:{}", consumeConcurrentlyContext.getMessageQueue().getTopic(), msg);
+        process(msg);
+        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
+    }
+
+    public void process(String content) {
+        final ExecutorService exec = Executors.newFixedThreadPool(1);
+        Callable<String> call = (Callable<String>) () -> {
+            //开始执行耗时操作
+            String[] strs = content.split(":;");
+            try {
+                String key = RedisKey.SCENE_BUILDING + strs[4];
+                // 获取缓存锁,防止重复消费
+                Long building = redisTemplate.opsForValue().increment(key, 1);
+                if (building.compareTo(1L) != 0) {
+                    log.error("场景正在构建中,退出构建,当前服务器id:{},参数:{}", SysConstants.hostName, content);
+                } else {
+                    redisTemplate.expire(key, Duration.of(SysConstants.modelTimeOut, ChronoUnit.HOURS));
+                }
+                //休眠2秒等待数据入库
+                Thread.sleep(2000L);
+                try {
+                    FileUtils.writeFile("/opt/hosts/running.txt", DateUtil.formatDateTime(new Date()));
+                    String tomcatLog = "scenenum:" + content + "\ntime:" + DateUtil.formatDateTime(new Date()) +
+                            " action:create hostname:" + SysConstants.hostName;
+                    //打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
+                    FileWriter writer = new FileWriter("/mnt/elastic_log/tomcat" + "_" + strs[4] + ".log", true);
+                    writer.write(tomcatLog);
+                    writer.close();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+
+                BuildSceneReceiver.this.buildScene(content);
+                redisTemplate.delete(key);
+                try {
+                    FileUtils.deleteFile("/opt/hosts/running.txt");
+                    String tomcatLog = "scenenum:" + content + "\ntime:" + DateUtil.formatDateTime(new Date()) +
+                            " action:delete hostname:" + SysConstants.hostName;
+                    //打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
+                    FileWriter writer = new FileWriter("/mnt/elastic_log/tomcat" + "_" + strs[4] + "log", true);
+                    writer.write(tomcatLog);
+                    writer.close();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+                sceneProService.updateStatus(strs[4], -1);
+                BuildSceneReceiver.this.handFail("计算失败", content);
+            }
+            log.info("场景生成好了***");
+            return "success";
+        };
+        Future<String> future = exec.submit(call);
+        try {
+            future.get(SysConstants.modelTimeOut, TimeUnit.MILLISECONDS); //任务处理超时时间设为 24个小时
+        } catch (TimeoutException ex) {
+            ex.printStackTrace();
+            StringWriter trace=new StringWriter();
+            ex.printStackTrace(new PrintWriter(trace));
+            log.error("超时了");
+            log.error(trace.toString());
+            FileUtils.deleteFile("/opt/hosts/running.txt");
+            future.cancel(true);
+            handFail("计算超时",content);
+        } catch (Exception e) {
+            e.printStackTrace();
+            StringWriter trace=new StringWriter();
+            e.printStackTrace(new PrintWriter(trace));
+            log.error(trace.toString());
+            FileUtils.deleteFile("/opt/hosts/running.txt");
+            future.cancel(true);
+            handFail("计算失败",content);
+        }
+
+    }
+
+    private void buildScene(String content){
+        String projectNum = null;
+        SceneFileBuild sceneFileBuildEntity = null;
+        ScenePro scene = null;
+        SceneProExt sceneProExt = null;
+        try{
+            String[] strs  = content.split(":;");
+
+            if(strs.length == 1){
+                //表示标定算法
+                Map<String,String> map = ComputerUtil.computerCalibration(strs[0]);
+                return;
+            }
+
+            String unicode = strs[0];
+            String path = strs[1];
+            String prefix = strs[2];
+            String imgsName = strs[3];
+            projectNum = strs[4];
+            String userName = strs[6];
+            //不同的相机不同的方法
+            String cameraType = strs[7];
+            String algorithm = strs[8];
+            String fileId = strs[9];
+            String cameraName = strs[10];
+            //0表示有4k图,1表示没有
+            String resolution = strs[11];
+
+            //判断调用V2还是V3版本的算法
+            String buildType = "V2";
+            if(strs.length >= 13){
+                buildType = strs[12];
+            }
+
+            String rebuild = "0";
+            if(strs.length >= 14){
+                rebuild = strs[13];
+            }
+            log.info("执行数据库操作--前");
+            sceneFileBuildEntity = sceneFileBuildService.findByFileId(fileId);
+            log.info("执行数据库操作--后");
+
+            Map<String, String> dataMap = ComputerUtil.getTypeString(cameraType, algorithm,
+                    resolution);
+            String splitType = dataMap.get("splitType");
+            String skyboxType = dataMap.get("skyboxType");
+            String dataDescribe = dataMap.get("dataDescribe");
+
+            log.info("用的算法是:"+algorithm);
+            log.info("用的相机是:"+ (Integer.parseInt(cameraType) < 4 ? "单球目" : "双球目(八目)"));
+            String isModel = strs[5];
+            Map<String,String> map = new HashMap<>();
+
+            //该场景使用的容量
+            Long space = 0L;
+            //支付状态
+            int payStatus = 0;
+            //4表示硬件部研发的双球目相机,其余为旧版本相机
+            if(Integer.parseInt(cameraType) < 3){
+
+                for(int i = 0;i<5;++i){
+                    try{
+                        FileUtils.downLoadFromUrl(prefix+imgsName+"?m="+new Date().getTime(), imgsName,
+                                path + File.separator + "capture");
+                        FileUtils.decompress(path + File.separator + "capture" +File.separator+imgsName,
+                                path + File.separator + "capture") ;
+                        break;
+                    }
+                    catch(Exception e){
+                        e.printStackTrace();
+                        StringWriter trace=new StringWriter();
+                        e.printStackTrace(new PrintWriter(trace));
+                        log.error(trace.toString());
+                        if(i<4)
+                        {
+                            FileUtils.deleteFile(path + File.separator + "capture" +File.separator+imgsName);
+                            FileUtils.delFolder(path + File.separator + "capture" +File.separator+"images");
+                        }
+                        Thread.sleep(10000);
+                    }
+                }
+
+                FileUtils.deleteFile(path + File.separator + "capture" +File.separator+"zip.Zip");
+
+                String data = FileUtils.readFile(path + File.separator + "capture" +File.separator+"data.fdage");
+                JSONObject dataJson = new JSONObject();
+                if(data!=null){
+                    dataJson = JSONObject.parseObject(data);
+                    if(dataJson.containsKey("imgs")){
+                        splitType = "SPLIT_V4";
+                    }
+                }
+                //生成project.json和data.json供算法部使用
+                ComputerUtil.createJson(path, splitType, skyboxType, dataDescribe, projectNum, path);
+                //计算模型并返回需要上传oss的文件集合
+                map = ComputerUtil.computer(projectNum, path, buildType);
+
+                uploadUtils.uploadMulFiles(map);
+                log.info("双目上完oss结束修改数据:"+projectNum);
+                sceneService.updateTime(projectNum, space, payStatus);
+            } else {
+
+                //休眠1秒,否则可能获取不到场景资源
+                Thread.sleep(1000);
+                scene = sceneProService.findBySceneNum(projectNum);
+                sceneProExt = sceneProExtService.lambdaQuery().eq(SceneProExt::getSceneProId, scene.getId()).getEntity();
+                if(scene == null){
+                    log.info(projectNum + ":场景不存在");
+                    handFail("场景不存在",content);
+                    return;
+                }
+
+                long start = System.currentTimeMillis();
+
+                //cameraType=5为新版本双目, cameraType=6为小红屋新版本双目
+                if(Integer.parseInt(cameraType) == 5 || Integer.parseInt(cameraType) == 6){
+                    path = ConstantFilePath.BUILD_MODEL_PATH + unicode;
+
+                    //下载zip包,并解压
+                    FileUtils.downLoadFromUrl(prefix + "/" + imgsName + "?m=" + System.currentTimeMillis(), imgsName, path + File.separator + "capture");
+                    FileUtils.decompress(path + File.separator + "capture" + File.separator + imgsName,
+                            path + File.separator + "capture") ;
+                    FileUtil.delFile(path + File.separator + "capture" + File.separator + imgsName);
+                }else if(Integer.parseInt(cameraType) == 14 ) {
+                    CreateObjUtil.ossUtilCp(ConstantFilePath.OSS_PREFIX + cameraName.replace("4DKKPRO_", "")
+                                    .replace("-fdage", "").toLowerCase() + File.separator + fileId + File.separator
+                                    + unicode + File.separator,
+                            ConstantFilePath.BUILD_MODEL_LASER_PATH + cameraName.replace("4DKKPRO_", "")
+                                    .replace("-fdage", "").toLowerCase() + File.separator + fileId + File.separator
+                                    + unicode + File.separator + "capture");
+                    path = ConstantFilePath.BUILD_MODEL_LASER_PATH + cameraName.replace("4DKKPRO_", "").replace("-fdage", "").toLowerCase() + File.separator + fileId + File.separator + unicode;
+                } else if(Integer.parseInt(cameraType) >= 4 ) {
+                    CreateObjUtil.ossUtilCp(ConstantFilePath.OSS_PREFIX + cameraName.replace("4DKKPRO_", "")
+                            .replace("-fdage", "").toLowerCase() + File.separator + fileId + File.separator
+                            + unicode + File.separator,
+                            ConstantFilePath.BUILD_MODEL_PATH + cameraName.replace("4DKKPRO_", "")
+                                    .replace("-fdage", "").toLowerCase() + File.separator + fileId + File.separator
+                                    + unicode + File.separator + "capture");
+                    path = ConstantFilePath.BUILD_MODEL_PATH + cameraName.replace("4DKKPRO_", "").replace("-fdage", "").toLowerCase() + File.separator + fileId + File.separator + unicode;
+                }
+                String data = FileUtils.readFile(path + File.separator + "capture" +File.separator+"data.fdage");
+                //获取data.fdage的内容
+                JSONObject dataJson = new JSONObject();
+                if(data!=null){
+                    dataJson = JSONObject.parseObject(data);
+                }
+                //判断是否计算过资源,若计算过删除缓存
+                File caches = new File(path + File.separator + "caches");
+                if(caches.exists()){
+                    for(File deleteFile : caches.listFiles()){
+                        if(new File(path + "_images").exists()){
+                            if(deleteFile.isDirectory()){
+                                FileUtils.delAllFile(deleteFile.getAbsolutePath());
+                            }else {
+                                FileUtils.deleteFile(deleteFile.getAbsolutePath());
+                            }
+                        }
+                        else if(!deleteFile.getAbsolutePath().contains("images")){
+                            if(deleteFile.isDirectory()){
+                                FileUtils.delAllFile(deleteFile.getAbsolutePath());
+                            }else {
+                                FileUtils.deleteFile(deleteFile.getAbsolutePath());
+                            }
+                        }
+                    }
+                }
+                if(new File(path + File.separator + "results").exists()){
+                    FileUtils.delAllFile(path + File.separator + "results");
+                }
+
+                //生成project.json和data.json供算法部使用
+                log.info("path:" + path);
+
+                if(dataJson.containsKey("videoVersion") && StringUtils.isNotEmpty(dataJson.getString("videoVersion")) && Integer.parseInt(dataJson.getString("videoVersion")) < 4){
+                    //v2版本使用4k算法
+                    skyboxType = "SKYBOX_V6";
+                }
+
+                ComputerUtil.createJson(path, splitType, skyboxType, dataDescribe, projectNum, path);
+                //计算模型并返回需要上传oss的文件集合
+                map = ComputerUtil.computer(projectNum, path, buildType);
+
+                if(Integer.parseInt(cameraType) == 5 || Integer.parseInt(cameraType) == 6){
+                    map.put(path + File.separator + "capture/stitch_params.txt", "data/data" + projectNum + "/stitch_params.txt");
+                }
+                map.put(path + File.separator + "capture/Up.xml", "data/data" + projectNum + "/Up.xml");
+                map.put(path + File.separator + "capture/Up2.xml", "data/data" + projectNum + "/Up2.xml");
+
+                if(Integer.parseInt(cameraType) == 13){
+                    //转台相机
+                    map.put(path + File.separator + "capture/Up.txt", "data/data" + projectNum + "/Up.txt");
+                    map.put(path + File.separator + "capture/Up2.txt", "data/data" + projectNum + "/Up2.txt");
+                }
+
+                uploadUtils.uploadMulFiles(map);
+                payStatus = 1;
+
+                File spaceFile = null;
+                for (String key : map.keySet()) {
+                    spaceFile = new File(key);
+                    if(spaceFile.exists()){
+                        space += spaceFile.length();
+                    }
+                }
+
+                log.info("八目上完oss结束修改数据:"+projectNum);
+
+                //获取upload中的video视频名称
+                String uploadData = FileUtils.readFile(path + File.separator + "results" +File.separator+"upload.json");
+                com.alibaba.fastjson.JSONObject uploadJson = null;
+                JSONArray array = null;
+                if(uploadData!=null) {
+                    uploadJson = com.alibaba.fastjson.JSONObject.parseObject(uploadData);
+                    array = uploadJson.getJSONArray("upload");
+                }
+                com.alibaba.fastjson.JSONObject fileJson = null;
+                String fileName = "";
+
+                //读取videos_hdr_param.json, 保存点位视频的value
+                Map<String, Object> videoMap = new HashMap<>();
+                String videosHdr = FileUtils.readFile(path + File.separator + "results/videos/videos_hdr_param.json");
+                JSONArray videoArray = null;
+                if(StringUtils.isNotEmpty(videosHdr)){
+                    videoArray = com.alibaba.fastjson.JSONObject.parseObject(videosHdr).getJSONArray("hdr_param");
+                }
+                if(videoArray != null){
+                    for(int i = 0, len = videoArray.size(); i < len; i++) {
+                        videoMap.put(videoArray.getJSONObject(i).getString("name"), videoArray.getJSONObject(i).getString("value"));
+                        if(videoArray.getJSONObject(i).containsKey("fov")){
+                            videoMap.put(videoArray.getJSONObject(i).getString("name") + "_fov", videoArray.getJSONObject(i).getString("fov"));
+                        }
+                    }
+                }
+
+                //计算ts文件的大小,并拼接成json格式
+                JSONArray jsonArray = new JSONArray();
+                com.alibaba.fastjson.JSONObject videoJson = null;
+                com.alibaba.fastjson.JSONObject videosJson = new com.alibaba.fastjson.JSONObject();
+                long videoSize = 0L;
+                for(int i = 0, len = array.size(); i < len; i++) {
+                    fileJson = array.getJSONObject(i);
+                    fileName = fileJson.getString("file");
+                    if(fileJson.getIntValue("clazz") == 11 && fileName.contains(".mp4") && !fileName.contains("-ios.mp4")){
+                        videoJson = new com.alibaba.fastjson.JSONObject();
+                        videoJson.put("id", fileName.substring(
+                                0, fileName.lastIndexOf(".")).replace("videos/", ""));
+
+                        //如果ts文件存在,就计算ts大小
+                        if(new File(path + File.separator + "results" +File.separator+ fileName.replace(".mp4", ".ts")).exists()){
+                            videoSize = new File(path + File.separator + "results" +File.separator+ fileName.replace(".mp4", ".ts")).length();
+                            videoJson.put("tsSize", videoSize);
+                        }
+                        if(videoMap.containsKey(videoJson.get("id"))){
+                            videoJson.put("value", videoMap.get(videoJson.get("id")));
+                        }
+                        if(videoMap.containsKey(videoJson.get("id") + "_fov")){
+                            videoJson.put("blend_fov", videoMap.get(videoJson.get("id") + "_fov"));
+                        }else {
+                            videoJson.put("blend_fov", 7);
+                        }
+                        jsonArray.add(videoJson);
+                    }
+                }
+
+                videosJson.put("data", jsonArray);
+                if(dataJson.containsKey("videoVersion") && StringUtils.isNotEmpty(dataJson.getString("videoVersion")) && Integer.parseInt(dataJson.getString("videoVersion")) >= 4){
+                    videosJson.put("version", 3);
+                    if("oss".equals(ossType)){
+                        videosJson.put("upPath", prefixAli + "data/data" + projectNum + "/Up.xml");
+                    }
+                    if("s3".equals(ossType)){
+                        videosJson.put("upPath", ConstantUrl.PREFIX_AWS + "data/data" + projectNum + "/Up.xml");
+                    }
+                    if(Integer.parseInt(cameraType) == 13){
+                        //转台相机
+                        videosJson.put("upPath", videosJson.getString("upPath").replace(".xml", ".txt"));
+                    }
+                }else {
+                    videosJson.put("version", 1);
+                    if("oss".equals(ossType)){
+                        videosJson.put("upPath", prefixAli + "data/data" + projectNum + "/Up2.xml");
+                    }
+                    if("s3".equals(ossType)){
+                        videosJson.put("upPath", ConstantUrl.PREFIX_AWS + "data/data" + projectNum + "/Up2.xml");
+                    }
+
+                    if(Integer.parseInt(cameraType) == 13){
+                        //转台相机
+                        videosJson.put("upPath", videosJson.getString("upPath").replace(".xml", ".txt"));
+                    }
+                }
+
+                if(Integer.parseInt(cameraType) == 5 || Integer.parseInt(cameraType) == 6){
+                    videosJson.put("version", 1);
+                    if("oss".equals(ossType)){
+                        videosJson.put("upPath", prefixAli + "data/data" + projectNum + "/stitch_params.txt");
+                    }
+                    if("s3".equals(ossType)){
+                        videosJson.put("upPath", ConstantUrl.PREFIX_AWS + "data/data" + projectNum + "/stitch_params.txt");
+                    }
+                }
+
+                long computeTime = (System.currentTimeMillis() - start) / 1000;
+                sceneProService.updateTime(projectNum, space, payStatus, videosJson.toJSONString(), computeTime);
+
+                //更新scene.json里面的video数据
+                StringBuffer dataBuf = new StringBuffer()
+                        .append("data").append(File.separator)
+                        .append("data").append(projectNum)
+                        .append(File.separator);
+                StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());
+                String strsceneInfos = FileUtils.readFile(dataBuffer.toString() + "scene.json");
+                com.alibaba.fastjson.JSONObject scenejson = new com.alibaba.fastjson.JSONObject();
+                if(strsceneInfos!=null){
+                    scenejson = com.alibaba.fastjson.JSONObject.parseObject(strsceneInfos);
+                }
+                scenejson.put("videos", videosJson.toJSONString());
+                FileUtils.writeFile(dataBuffer.toString() + "scene.json", scenejson.toString());
+
+                User userEntity = userService.findByUserName(userName);
+                if(userEntity == null){
+                    userService.updateUserUsedSpaceBySceneNum(null, projectNum);
+                }else {
+                    userService.updateUserUsedSpaceBySceneNum(userEntity.getId(), projectNum);
+                }
+                if (sceneFileBuildEntity != null){
+                    sceneFileBuildEntity.setBuildStatus(3);
+                    sceneFileBuildService.update(sceneFileBuildEntity);
+                }
+
+                //根据data.fdage推送计算完成的消息
+                log.info("推送消息,渠道是 {}, 手机token是 {}", dataJson.get("pushChannel"), dataJson.get("pushToken"));
+                if(dataJson.containsKey("pushChannel") && dataJson.containsKey("pushToken")){
+                    try{
+                        if(!"s3".equals(ossType)){
+                            PushMessageConfig demo = null;
+                            if(dataJson.getIntValue("pushChannel") == 0){
+
+                                if(Integer.parseInt(cameraType) == 10 || Integer.parseInt(cameraType) == 13){
+                                    //ios
+                                    log.info("IOS_KEY:{}, IOS_SECRET:{}", IOS_KEY_Z, IOS_SECRET_Z);
+                                    demo = new PushMessageConfig(IOS_KEY_Z, IOS_SECRET_Z);
+                                    demo.sendIOSUnicast(dataJson.getString("pushToken"),
+                                            "四维看看Minion", scene.getSceneName() + "计算完成", "您上传的" + scene.getSceneName() + "计算完成,点击查看",
+                                            scene.getWebSite());
+                                }else {
+                                    //ios
+                                    log.info("IOS_KEY:{}, IOS_SECRET:{}", IOS_KEY, IOS_SECRET);
+                                    demo = new PushMessageConfig(IOS_KEY, IOS_SECRET);
+                                    demo.sendIOSUnicast(dataJson.getString("pushToken"),
+                                            "四维看看Pro", scene.getSceneName() + "计算完成", "您上传的" + scene.getSceneName() + "计算完成,点击查看",
+                                            scene.getWebSite());
+                                }
+
+                            }else {
+                                if(Integer.parseInt(cameraType) == 10 || Integer.parseInt(cameraType) == 13){
+                                    //ios
+                                    //安卓
+                                    log.info("ANDROID_KEY:{}, ANDROID_SECRET:{}", ANDROID_KEY_Z, ANDROID_SECRET_Z);
+                                    demo = new PushMessageConfig(ANDROID_KEY_Z, ANDROID_SECRET_Z);
+                                    demo.sendAndroidUnicast2(dataJson.getString("pushToken"),
+                                            "四维看看Minion", scene.getSceneName() + "计算完成", "您上传的" + scene.getSceneName() + "计算完成,点击查看",
+                                            scene.getWebSite());
+                                }else {
+                                    //安卓
+                                    log.info("ANDROID_KEY:{}, ANDROID_SECRET:{}", ANDROID_KEY, ANDROID_SECRET);
+                                    demo = new PushMessageConfig(ANDROID_KEY, ANDROID_SECRET);
+                                    demo.sendAndroidUnicast(dataJson.getString("pushToken"),
+                                            "四维看看Pro", scene.getSceneName() + "计算完成", "您上传的" + scene.getSceneName() + "计算完成,点击查看",
+                                            scene.getWebSite());
+                                }
+                            }
+
+                        }else {
+                            PushMsgUtil.googlePushMsg(dataJson.getString("pushToken"),
+                                    scene.getSceneName() + "计算完成", "您上传的" + scene.getSceneName() + "计算完成,点击查看",
+                                    scene.getWebSite());
+                        }
+                        log.info("消息推送结束!");
+                    }catch (Exception e){
+                        log.info("推送消息失败:");
+                        e.printStackTrace();
+                    }
+                }
+
+                //计算成功  激光转台相机推送
+                log.info("激光转台相机 同步 请求 ");
+                if(Integer.parseInt(cameraType) == 14){
+                    try {
+                        String title = "";
+                        if(StringUtils.isNotEmpty(scene.getSceneName())){
+                            title = scene.getSceneName();
+                        }
+                        String dataSource = sceneProExt.getDataSource();
+                        String jgPath = dataSource;
+                        //创建目录
+                        if(dataSource.lastIndexOf("/")!=-1){
+                            jgPath = jgPath + "_laserData";
+                        }else{
+                            jgPath = jgPath.substring(0,jgPath.length()-1) + "_laserData";
+                        }
+
+                        FileUtils.createDir(jgPath+"/extras");
+
+                        log.info("生成 激光相机目录 " + jgPath);
+                        //生成data.json
+                        JSONObject jgDataJson = new JSONObject();
+                        jgDataJson.put("split_type", "SPLIT_V15");
+                        jgDataJson.put("skybox_type", "SKYBOX_V5");
+                        jgDataJson.put("extras", null);
+                        FileUtils.writeFile(jgPath + File.separator + "data.json", jgDataJson.toString());
+
+                        CreateObjUtil.cpfile(dataSource  + "/results/laserData/cover", jgPath+"/extras/");
+                        CreateObjUtil.cplaserfile(dataSource  + "/results/laserData", jgPath+File.separator);
+
+                        //激光相机
+                        String url = laserHost+"/indoor/{sceneCode}/api/init?path="
+                                        + jgPath + File.separator + "laserData" + "&title="+ title
+                                        + "&childName=" + cameraName + "&createTime=" + scene.getCreateTime()
+                                        + "&snCode="+ cameraName;
+
+                        if(scene.getUserId()!=null){
+                            url = url + "&userId=" + scene.getUserId();
+                        }
+
+                        if(StringUtils.isNotEmpty(userName)){
+                            url = url + "&phone=" + userName;
+                        }
+
+                        url = url.replace("{sceneCode}",scene.getSceneCode());
+                        log.info("激光转台相机 同步 :" + url);
+                        com.alibaba.fastjson.JSONObject hotListJson =
+                                com.alibaba.fastjson.JSONObject.parseObject(restTemplate.getForObject(url,String.class));
+                        log.info("激光转台相机 同步结束 :" + hotListJson);
+                    }catch (Exception e){
+                        e.printStackTrace();
+                        handFail("激光转台相机同步失败",content);
+                    }
+                }
+            }
+
+            CreateObjUtil.deleteFile(path.replace(ConstantFilePath.BUILD_MODEL_PATH, "/") + "/capture");
+        } catch(Exception e){
+            log.error("计算大场景失败"+projectNum);
+            sceneService.updateStatus(projectNum, -1);
+            sceneProService.updateStatus(projectNum, -1);
+            if (sceneFileBuildEntity != null){
+                sceneFileBuildEntity.setBuildStatus(-1);
+                sceneFileBuildService.update(sceneFileBuildEntity);
+            }
+            e.printStackTrace();
+            StringWriter trace=new StringWriter();
+            e.printStackTrace(new PrintWriter(trace));
+            log.error(trace.toString());
+            handFail("计算失败",content);
+        }finally {
+            try{
+                scene = sceneProService.findBySceneNum(projectNum);
+                if(scene != null){
+                    com.alibaba.fastjson.JSONObject statusJson = new com.alibaba.fastjson.JSONObject();
+                    //临时将-2改成1,app还没完全更新
+                    int status = sceneProExt.getSceneStatus();
+                    if(status == -2){
+                        status = 1;
+                    }else if(status == -1){
+                        // 失败状态不予显示到客户端
+                        status = 0;
+                    }
+                    statusJson.put("status", status);
+                    statusJson.put("webSite", scene.getWebSite());
+                    statusJson.put("sceneNum", scene.getSceneCode());
+                    statusJson.put("thumb", scene.getThumb());
+                    statusJson.put("payStatus", sceneProExt.getPayStatus());
+                    FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data/data"+projectNum+File.separator+"status.json", statusJson.toString());
+                    uploadUtils.upload(ConstantFilePath.SCENE_PATH+"data/data"+projectNum+File.separator+"status.json",
+                            "data/data"+projectNum+File.separator+"status.json");
+
+                    //上送日志
+                    uploadUtils.upload(sceneProExt.getDataSource()+File.separator+"console.log",
+                            "build_log/"+scene.getSceneCode()+File.separator+"console.log");
+
+
+                }
+            }catch (Exception e){
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private void kanfangBuild(String content){
+
+        JSONObject json = JSONObject.parseObject(content);
+        String sceneName = json.getString("sceneName");
+        String sceneNum = json.getString("sceneNum");
+
+        // 获取缓存锁,防止重复消费
+        Long building = redisTemplate.opsForValue().increment(RedisKey.SCENE_BUILDING + sceneNum, 1);
+        if (building.compareTo(1L) != 0) {
+            log.error("场景正在构建中,退出构建,当前服务器id:{},参数:{}", SysConstants.hostName,content);
+            return;
+        }
+
+        int sceneScheme = json.getIntValue("sceneScheme");
+        long userId = json.getLong("userId");
+        String dataSource = json.getString("dataSource");
+        String queue = json.getString("callbackQueue");
+        log.info("sceneName: {}, sceneNum: {}, sceneScheme: {}, userId: {}, dataSource:{}, queue:{}",
+                sceneName, sceneNum, sceneScheme, userId, dataSource, queue);
+
+        JSONObject result = new JSONObject();
+        result.put("sceneNum", sceneNum);
+
+        try{
+            ScenePro scenePro = sceneProService.findBySceneNum(sceneNum);
+
+            if(scenePro == null){
+                scenePro = new ScenePro();
+                SceneProExt sceneProExt = new SceneProExt();
+
+                sceneProExt.setDataSource(dataSource);
+                scenePro.setSceneName(sceneName);
+                scenePro.setSceneCode(sceneNum);
+                scenePro.setUserId(userId);
+                scenePro.setSceneScheme(sceneScheme);
+                sceneProExt.setSceneStatus(0);
+                scenePro.setWebSite(mainUrl + sceneProNewUrl + sceneNum);
+                sceneProExt.setPayStatus(1);
+                scenePro.setBuildType("V3");
+                sceneProExt.setSceneSource(12);
+                scenePro.setSceneDec("<p>快速打造3D空间模型,让三维数字技术服务于生活。</p>");
+                sceneProService.save(scenePro);
+                sceneProExtService.save(sceneProExt);
+
+                SceneProEdit sceneEdit = new SceneProEdit();
+                SceneProEditExt sceneEditExt = new SceneProEditExt();
+                sceneEdit.setNeedKey(0);
+
+                sceneEdit.setProId(scenePro.getId());
+                sceneEditExt.setMapVisi(1);
+                sceneEditExt.setTourVisi(1);
+                sceneEditExt.setVrVisi(1);
+                sceneEditExt.setRulerVisi(1);
+                sceneEditExt.setCadImgVisi(1);
+                sceneEditExt.setPanoVisi(1);
+                sceneEditExt.setM2dVisi(1);
+                sceneEditExt.setM3dVisi(1);
+                sceneEditExt.setMeasureVisi(0);
+                sceneEdit.setFloorLogoSize(100);
+                sceneEdit.setCreateTime(new Date());
+                sceneProEditService.save(sceneEdit);
+                sceneProEditExtService.save(sceneEditExt);
+
+                //生成二维码logo
+                restTemplate.getForObject(mainUrl + "api/scene/createSketchQrLogo?sceneNum=" + sceneNum,String.class);
+            }else {
+
+                SceneProExt sceneProExt = sceneProExtService.lambdaQuery()
+                        .eq(SceneProExt::getSceneProId,scenePro.getId()).getEntity();
+
+                sceneProExt.setDataSource(dataSource);
+                scenePro.setSceneName(sceneName);
+                scenePro.setSceneCode(sceneNum);
+                scenePro.setUserId(userId);
+                scenePro.setSceneScheme(sceneScheme);
+                sceneProExt.setSceneStatus(0);
+                scenePro.setWebSite(mainUrl + sceneProNewUrl + sceneNum);
+                sceneProExt.setPayStatus(1);
+                scenePro.setBuildType("V3");
+                sceneProExt.setSceneSource(12);
+                sceneProService.updateById(scenePro);
+                sceneProExtService.updateById(sceneProExt);
+
+                SceneProEdit sceneEdit = sceneProEditService.lambdaQuery()
+                        .eq(SceneProEdit::getProId,scenePro.getId()).getEntity();
+
+                SceneProEditExt sceneProEditExt = sceneProEditExtService.lambdaQuery()
+                        .eq(SceneProEditExt::getProEditId,sceneEdit.getId()).getEntity();
+
+                sceneEdit.setNeedKey(0);
+
+                sceneEdit.setProId(scenePro.getId());
+                sceneEdit.setVersion(sceneEdit.getVersion() + 1);
+                sceneProEditExt.setImagesVersion(sceneProEditExt.getImagesVersion() + 1);
+                sceneEdit.setFloorEditVer(sceneEdit.getFloorEditVer() + 1);
+                sceneEdit.setFloorPublishVer(sceneEdit.getFloorPublishVer() + 1);
+                sceneEdit.setUpdateTime(new Date());
+                sceneProEditService.updateById(sceneEdit);
+                sceneProEditExtService.updateById(sceneProEditExt);
+            }
+
+
+            com.alibaba.fastjson.JSONObject scenejson = com.alibaba.fastjson.JSONObject.parseObject(com.alibaba.fastjson.JSONObject.toJSONString(scenePro));
+            FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data/data"+sceneNum+File.separator+"scene.json", scenejson.toString());
+
+            //计算模型并返回需要上传oss的文件集合
+            Map map = ComputerUtil.computer(sceneNum, dataSource, "V3");
+            uploadUtils.uploadMulFiles(map);
+
+            sceneProService.updateStatus(sceneNum, -2);
+
+            log.info("计算完成,发送mq通知123看房");
+
+            result.put("result", 1);
+            result.put("code", 0);
+            result.put("msg", "计算完成");
+            Message msg = new Message(queue,JSONObject.toJSONString(result).getBytes());
+            mqProducer.send(msg);
+        }catch (Exception e){
+            sceneProService.updateStatus(sceneNum, -1);
+
+            log.info("计算失败,发送mq通知123看房");
+
+            result.put("result", 0);
+            result.put("code", 500);
+            result.put("msg", "计算失败");
+
+            Message msg = new Message(queue,JSONObject.toJSONString(result).getBytes());
+            try {
+                mqProducer.send(msg);
+            } catch (Exception ee) {
+                ee.printStackTrace();
+            }
+            handFail("看房场景计算失败",dataSource,sceneNum);
+        }
+    }
+
+    private void handFail(String reason,String content){
+        String serverPath = "";
+        String num = "";
+        if(content.contains(":;")){
+            String[] strs  = content.split(":;");
+            serverPath = strs[1].substring(0,strs[1].lastIndexOf("/")+1).concat(strs[2]);
+            num = strs[4];
+        }else{
+            JSONObject json = JSONObject.parseObject(content);
+            num = json.getString("sceneNum");
+            serverPath = json.getString("dataSource");
+        }
+        handFail(reason,serverPath,num);
+    }
+
+    private void handFail(String reason,String serverPath,String num){
+        // 释放缓存锁
+        redisTemplate.delete(RedisKey.SCENE_BUILDING + num);
+        CompletableFuture.runAsync(() -> {
+            try {
+                DingDingUtils.sendMsgToDingRobot(reason,serverPath,num);
+            } catch (ApiException | UnsupportedEncodingException | NoSuchAlgorithmException | InvalidKeyException apiException) {
+                apiException.printStackTrace();
+            }
+        });
+    }
+}

+ 19 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/ISceneFileBuildService.java

@@ -0,0 +1,19 @@
+package com.fdkankan.modeling.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.modeling.entity.SceneFileBuild;
+
+/**
+ * <p>
+ * 场景文件建模表 服务类
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+public interface ISceneFileBuildService extends IService<SceneFileBuild> {
+
+    SceneFileBuild findByFileId(String fileId);
+
+    void update(SceneFileBuild sceneFileBuildEntity);
+}

+ 16 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/ISceneProEditExtService.java

@@ -0,0 +1,16 @@
+package com.fdkankan.modeling.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.modeling.entity.SceneProEditExt;
+
+/**
+ * <p>
+ * pro场景编辑数据表 服务类
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+public interface ISceneProEditExtService extends IService<SceneProEditExt> {
+
+}

+ 16 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/ISceneProEditService.java

@@ -0,0 +1,16 @@
+package com.fdkankan.modeling.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.modeling.entity.SceneProEdit;
+
+/**
+ * <p>
+ * pro场景编辑数据表 服务类
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+public interface ISceneProEditService extends IService<SceneProEdit> {
+
+}

+ 16 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/ISceneProExtService.java

@@ -0,0 +1,16 @@
+package com.fdkankan.modeling.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.modeling.entity.SceneProExt;
+
+/**
+ * <p>
+ * pro场景表 服务类
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+public interface ISceneProExtService extends IService<SceneProExt> {
+
+}

+ 21 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/ISceneProService.java

@@ -0,0 +1,21 @@
+package com.fdkankan.modeling.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.modeling.entity.ScenePro;
+
+/**
+ * <p>
+ * pro场景表 服务类
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+public interface ISceneProService extends IService<ScenePro> {
+
+    void updateStatus(String str, int i);
+
+    ScenePro findBySceneNum(String projectNum);
+
+    void updateTime(String projectNum, Long space, int payStatus, String toJSONString, long computeTime);
+}

+ 19 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/ISceneService.java

@@ -0,0 +1,19 @@
+package com.fdkankan.modeling.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.modeling.entity.Scene;
+
+/**
+ * <p>
+ * 场景表 服务类
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+public interface ISceneService extends IService<Scene> {
+
+    void updateTime(String projectNum, Long space, int payStatus);
+
+    void updateStatus(String projectNum, int i);
+}

+ 18 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/IUserService.java

@@ -0,0 +1,18 @@
+package com.fdkankan.modeling.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.modeling.entity.User;
+
+/**
+ * <p>
+ * 用户信息表 服务类
+ * </p>
+ *
+ * @author 
+ * @since 2021-12-24
+ */
+public interface IUserService extends IService<User> {
+    User findByUserName(String userName);
+
+    void updateUserUsedSpaceBySceneNum(Object o, String projectNum);
+}

+ 29 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/impl/SceneFileBuildServiceImpl.java

@@ -0,0 +1,29 @@
+package com.fdkankan.modeling.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.modeling.entity.SceneFileBuild;
+import com.fdkankan.modeling.mapper.ISceneFileBuildMapper;
+import com.fdkankan.modeling.service.ISceneFileBuildService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 场景文件建模表 服务实现类
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+@Service
+public class SceneFileBuildServiceImpl extends ServiceImpl<ISceneFileBuildMapper, SceneFileBuild> implements ISceneFileBuildService {
+
+    @Override
+    public SceneFileBuild findByFileId(String fileId) {
+        return null;
+    }
+
+    @Override
+    public void update(SceneFileBuild sceneFileBuildEntity) {
+
+    }
+}

+ 20 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/impl/SceneProEditExtServiceImpl.java

@@ -0,0 +1,20 @@
+package com.fdkankan.modeling.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.modeling.entity.SceneProEditExt;
+import com.fdkankan.modeling.mapper.ISceneProEditExtMapper;
+import com.fdkankan.modeling.service.ISceneProEditExtService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * pro场景编辑数据表 服务实现类
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+@Service
+public class SceneProEditExtServiceImpl extends ServiceImpl<ISceneProEditExtMapper, SceneProEditExt> implements ISceneProEditExtService {
+
+}

+ 20 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/impl/SceneProEditServiceImpl.java

@@ -0,0 +1,20 @@
+package com.fdkankan.modeling.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.modeling.entity.SceneProEdit;
+import com.fdkankan.modeling.mapper.ISceneProEditMapper;
+import com.fdkankan.modeling.service.ISceneProEditService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * pro场景编辑数据表 服务实现类
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+@Service
+public class SceneProEditServiceImpl extends ServiceImpl<ISceneProEditMapper, SceneProEdit> implements ISceneProEditService {
+
+}

+ 20 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/impl/SceneProExtServiceImpl.java

@@ -0,0 +1,20 @@
+package com.fdkankan.modeling.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.modeling.entity.SceneProExt;
+import com.fdkankan.modeling.mapper.ISceneProExtMapper;
+import com.fdkankan.modeling.service.ISceneProExtService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * pro场景表 服务实现类
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+@Service
+public class SceneProExtServiceImpl extends ServiceImpl<ISceneProExtMapper, SceneProExt> implements ISceneProExtService {
+
+}

+ 35 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/impl/SceneProServiceImpl.java

@@ -0,0 +1,35 @@
+package com.fdkankan.modeling.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.modeling.entity.ScenePro;
+import com.fdkankan.modeling.mapper.ISceneProMapper;
+import com.fdkankan.modeling.service.ISceneProService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * pro场景表 服务实现类
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2021-12-23
+ */
+@Service
+public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro> implements ISceneProService {
+
+
+    @Override
+    public void updateStatus(String str, int i) {
+
+    }
+
+    @Override
+    public ScenePro findBySceneNum(String projectNum) {
+        return null;
+    }
+
+    @Override
+    public void updateTime(String projectNum, Long space, int payStatus, String toJSONString, long computeTime) {
+
+    }
+}

+ 24 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/impl/SceneServiceImpl.java

@@ -0,0 +1,24 @@
+package com.fdkankan.modeling.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.modeling.entity.Scene;
+import com.fdkankan.modeling.mapper.ISceneMapper;
+import com.fdkankan.modeling.service.ISceneService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class SceneServiceImpl extends ServiceImpl<ISceneMapper, Scene> implements ISceneService {
+
+
+    @Override
+    public void updateTime(String projectNum, Long space, int payStatus) {
+
+    }
+
+    @Override
+    public void updateStatus(String projectNum, int i) {
+
+    }
+}

+ 30 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/service/impl/UserServiceImpl.java

@@ -0,0 +1,30 @@
+package com.fdkankan.modeling.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.modeling.entity.User;
+import com.fdkankan.modeling.mapper.IUserMapper;
+import com.fdkankan.modeling.service.IUserService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 用户信息表 服务实现类
+ * </p>
+ *
+ * @author
+ * @since 2021-12-24
+ */
+@Service
+public class UserServiceImpl extends ServiceImpl<IUserMapper, User> implements IUserService {
+
+
+    @Override
+    public User findByUserName(String userName) {
+        return null;
+    }
+
+    @Override
+    public void updateUserUsedSpaceBySceneNum(Object o, String projectNum) {
+
+    }
+}

+ 332 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/utils/ComputerUtil.java

@@ -0,0 +1,332 @@
+package com.fdkankan.modeling.utils;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.common.constant.ConstantFileName;
+import com.fdkankan.common.constant.ConstantFilePath;
+import com.fdkankan.common.utils.CreateObjUtil;
+import com.fdkankan.common.utils.FileUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * 生成场景和计算场景
+ * Created by Hb_zzZ on 2019/5/8.
+ */
+@Slf4j
+@Component
+public class ComputerUtil {
+
+
+    public static Map<String,String> computer(String projectNum, String path, String buildType) throws Exception{
+        Map<String,String> map = new HashMap<String,String>();
+        path = path.replace("//", "/");
+
+        log.info("开始建模:"+projectNum);
+        //构建算法isModel去掉,因此改成空字符串
+        if("V2".equals(buildType)){
+            CreateObjUtil.build3dModelOld(path, "");
+        }
+        if("V3".equals(buildType)){
+            CreateObjUtil.build3dModel(path, "");
+//        CreateObjUtil.build3dModel(unicode, "");
+        }
+        log.info("建模完成转换数据:"+projectNum);
+
+        boolean vision2 = false;
+        //读取upload文件,检验需要上传的文件是否存在
+        String uploadData = FileUtils.readFile(path + File.separator + "results" +File.separator+"upload.json");
+        JSONObject uploadJson = null;
+        JSONArray array = null;
+        if(uploadData!=null) {
+            uploadJson = JSONObject.parseObject(uploadData);
+            array = uploadJson.getJSONArray("upload");
+        }
+        if(array == null){
+            String instanceId = FileUtils.readFile("/opt/hosts/hosts.txt");
+            FileUtils.writeFile(path + File.separator + "javaErrorNow.log", instanceId + ":计算错误!");
+
+            Thread.sleep(10000L);
+            FileUtils.writeFile(path + File.separator + "javaError.log", instanceId + ":计算错误!");
+            throw new Exception("upload.json数据出错");
+        }
+        JSONObject fileJson = null;
+        String fileName = "";
+        String meshfix = "";  //双模型时候会有改文件路径
+        for(int i = 0, len = array.size(); i < len; i++){
+            fileJson = array.getJSONObject(i);
+            fileName = fileJson.getString("file");
+            //文件不存在抛出异常
+            if(!new File(path + File.separator + "results" +File.separator + fileName).exists()){
+                throw new Exception(path + File.separator + "results" +File.separator + fileName+"文件不存在");
+            }
+
+            //判断是否有vision2.txt
+            if("vision2.txt".equals(fileName)){
+                vision2 = true;
+            }
+
+            //tex文件夹
+            if(fileJson.getIntValue("clazz") == 2 && !fileJson.containsKey("pack-file")){
+                if(fileName.contains("meshfix.txt")){
+                    meshfix = fileName;
+                }else {
+                    map.put(path + File.separator + "results" +File.separator+ fileName,"images/images"+
+                            projectNum+"/"+ ConstantFileName.modelUUID+"_50k_texture_jpg_high1/"+fileName.replace("tex/", ""));
+                }
+                continue;
+            }
+
+            //high文件夹
+            if(fileJson.getIntValue("clazz") == 3){
+                map.put(path + File.separator + "results" +File.separator+ fileName,"images/images"+
+                        projectNum+"/pan/high/"+ fileName.replace("high/", ""));
+                continue;
+            }
+            //low文件夹
+            if(fileJson.getIntValue("clazz") == 4){
+                map.put(path + File.separator + "results" +File.separator+ fileName,"images/images"+
+                        projectNum+"/pan/low/"+ fileName.replace("low/", ""));
+                continue;
+            }
+
+            //tiles文件夹,亚马逊没有裁剪图片api,不需要上传4k图
+//            if(fileJson.getIntValue("clazz") == 5 && !"s3".equals(ossType)){
+//                map.put(path + File.separator + "results" + File.separator+ fileName,"images/images"+
+//                        projectNum+ File.separator + fileName);
+//                continue;
+//            }
+            if(fileJson.getIntValue("clazz") == 5 ){
+                map.put(path + File.separator + "results" + File.separator+ fileName,"images/images"+
+                        projectNum+ File.separator + fileName);
+                continue;
+            }
+
+            //tiles文件夹,亚马逊瓦片图
+            if(fileJson.getIntValue("clazz") == 7 ){
+                if(fileName.contains("/4k_")){
+                    continue;
+                }
+                map.put(path + File.separator + "results" + File.separator+ fileName,"images/images"+
+                        projectNum+ File.separator + fileName);
+                continue;
+            }
+
+            //updown文件复制一份到ecs中并去掉换行符
+            if(fileJson.getIntValue("clazz") == 10){
+                String updown = FileUtils.readFile(path + File.separator + "results" +File.separator+ fileName);
+                JSONObject updownJson = JSONObject.parseObject(updown);
+                FileUtils.writeFile(ConstantFilePath.SCENE_PATH + "data" + File.separator + "data" + projectNum +
+                        File.separator + fileName.replace("updown", "mapping"), updownJson.toString());
+                continue;
+            }
+
+            //video视频文件或封面图
+            if(fileJson.getIntValue("clazz") == 11 || fileJson.getIntValue("cl" +
+                    "azz") == 12){
+                map.put(path + File.separator + "results" + File.separator+ fileName,"video/video"+
+                        projectNum+ File.separator + fileName.replace("videos/", ""));
+
+                if(fileName.contains(".mp4")){
+//                    CreateObjUtil.mp4ToFlv(path + File.separator + "results" + File.separator+ fileName,
+//                            path + File.separator + "results" + File.separator+ fileName.replace("mp4", "flv"));
+
+                    map.put(path + File.separator + "results" + File.separator+ fileName.replace("mp4", "flv"),"video/video"+
+                            projectNum+ File.separator + fileName.replace("videos/", "").replace("mp4", "flv"));
+                }
+            }
+
+            //2048的模型和贴图
+            if(fileJson.getIntValue("clazz") == 16){
+                map.put(path + File.separator + "results" + File.separator+ fileName,"data/data"+
+                        projectNum+ File.separator + fileName);
+            }
+
+            if(fileJson.getIntValue("clazz") == 18){
+                map.put(path + File.separator + "results" + File.separator+ fileName,"images/images"+
+                        projectNum+ File.separator + fileName);
+            }
+        }
+
+        CreateObjUtil.convertTxtToDam( path + File.separator + "results" + File.separator+"tex"+File.separator+"modeldata.txt", path + File.separator + "results" +File.separator+ ConstantFileName.modelUUID+"_50k.dam");
+        CreateObjUtil.convertDamToLzma(path + File.separator + "results");
+        CreateObjUtil.convertTxtToDam( path + File.separator + "results" +File.separator+"tex"+File.separator+"modeldata.txt", path + File.separator + "results" + File.separator+ConstantFileName.modelUUID+"_50k.dam");
+        //有meshfix,表示双模型
+        if(!"".equals(meshfix)){
+            CreateObjUtil.convertTxtToDam( path + File.separator + "results" + File.separator+meshfix, path + File.separator + "results" +File.separator+ ConstantFileName.modelUUID+"_50k2.dam");
+            CreateObjUtil.convertDamToLzma2(path + File.separator + "results");
+            CreateObjUtil.convertTxtToDam( path + File.separator + "results" +File.separator+meshfix, path + File.separator + "results" + File.separator+ConstantFileName.modelUUID+"_50k2.dam");
+            map.put(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k2.dam.lzma", "images/images"+projectNum+"/"+ConstantFileName.modelUUID+"_50k2.dam.lzma");
+            map.put(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k2.dam", "images/images"+projectNum+"/"+ConstantFileName.modelUUID+"_50k2.dam");
+        }
+        //8目相机有两个vision.txt因此第二个叫vision2.txt
+        CreateObjUtil.convertTxtToVisionmodeldata(path + File.separator + "results" +File.separator+"vision.txt",path + File.separator + "results" +File.separator+"vision.modeldata");
+        if(vision2){
+            CreateObjUtil.convertTxtToVisionmodeldata(path + File.separator + "results" +File.separator+"vision2.txt",path + File.separator + "results" +File.separator+"vision2.modeldata");
+            map.put(path + File.separator + "results" +File.separator+"vision2.modeldata", "images/images"+projectNum+"/"+"vision2.modeldata");
+        }else {
+            CreateObjUtil.convertTxtToVisionmodeldataCommon(path + File.separator + "results" +File.separator+"vision.txt",path + File.separator + "results" +File.separator+"vision.modeldata");
+        }
+        log.info("数据转换完成:"+projectNum);
+
+        File file = new File(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k.dam.lzma");
+        while(!file.exists())
+        {
+            Thread.sleep(60000);
+        }
+
+        map.put(path + File.separator + "results" +File.separator+"vision.modeldata", "images/images"+projectNum+"/"+"vision.modeldata");
+        map.put(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k.dam.lzma", "images/images"+projectNum+"/"+ConstantFileName.modelUUID+"_50k.dam.lzma");
+        map.put(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k.dam", "images/images"+projectNum+"/"+ConstantFileName.modelUUID+"_50k.dam");
+
+        file = new File(ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+projectNum);
+        if(!file.exists())
+        {
+            file.mkdir();
+        }
+        FileUtils.copyFile(path + File.separator + "results" +File.separator+"floor.json", ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+projectNum+File.separator+"floor.json", true);
+        FileUtils.copyFile(path + File.separator + "results" +File.separator+"floorplan.json", ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+projectNum+File.separator+"floor.json", true);
+        FileUtils.copyFile(path + File.separator + "results" +File.separator+"floorplan.json", ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+projectNum+File.separator+"floorplan.json", true);
+        log.info("floor.json路径:"+ path + File.separator + "results" +File.separator+"floor.json");
+        map.put(path + File.separator + "results" +File.separator+"floor.json","data/data"+projectNum+"/floor.json");
+        map.put(path + File.separator + "results" +File.separator+"floorplan.json","data/data"+projectNum+"/floor.json");
+//        map.put(path + File.separator + "results" +File.separator+"floorplan_cad.json","data/data"+projectNum+"/house_floor.json");
+        map.put(path + File.separator + "results" +File.separator+"floorplan_cad.json","data/data"+projectNum+"/floorplan_cad.json");
+        log.info("准备上传文件到oss:"+projectNum);
+        return map;
+    }
+
+    /**
+     *  标定算法
+     * @param path
+     * @throws Exception
+     */
+    public static Map<String,String> computerCalibration(String path) throws Exception{
+
+        Map<String,String> map = new HashMap<String,String>();
+
+        log.info("开始标定:" );
+        //构建算法isModel去掉,因此改成空字符串
+        CreateObjUtil.build3dModel(path, "");
+//        CreateObjUtil.build3dModel(unicode, "");
+        log.info("标定完成转换数据:" );
+
+        boolean vision2 = false;
+        //读取upload文件,检验需要上传的文件是否存在
+        String uploadData = FileUtils.readFile(path + File.separator + "results" +File.separator+"upload.json");
+        JSONObject uploadJson = null;
+        JSONArray array = null;
+        if(uploadData!=null) {
+            uploadJson = JSONObject.parseObject(uploadData);
+            array = uploadJson.getJSONArray("upload");
+        }
+        if(array == null){
+            throw new Exception("upload.json数据出错");
+        }
+        JSONObject fileJson = null;
+        String fileName = "";
+        for(int i = 0, len = array.size(); i < len; i++) {
+            fileJson = array.getJSONObject(i);
+            fileName = fileJson.getString("file");
+            //文件不存在抛出异常
+            if (!new File(path + File.separator + "results" + File.separator + fileName).exists()) {
+                throw new Exception(path + File.separator + "results" + File.separator + fileName + "文件不存在");
+            }
+
+            if(fileJson.getIntValue("clazz") == 13 || fileJson.getIntValue("clazz") == 14){
+                map.put(path + File.separator + "results" +File.separator+ fileName,
+                        ConstantFilePath.OSS_PREFIX + path.replace(ConstantFilePath.BUILD_MODEL_PATH, "") +
+                                File.separator + fileName);
+            }
+        }
+        return map;
+    }
+
+    public static void createJson(String path, String splitType, String skyboxType, String dataDescribe,
+                                  String sceneNum, String dataSource) throws Exception{
+        JSONObject projectJson = new JSONObject();
+        projectJson.put("version", "201909231830");
+        projectJson.put("protocol", "file api 1.4");
+        projectJson.put("uuid", UUID.randomUUID().toString());
+        projectJson.put("description", "");
+        projectJson.put("time", System.currentTimeMillis());
+        projectJson.put("category", "default");
+        projectJson.put("tag", null);
+        projectJson.put("status", null);
+        projectJson.put("sceneNum", sceneNum);
+        projectJson.put("dataSource", dataSource);
+        FileUtils.writeFile(path + File.separator + "project.json", projectJson.toString());
+
+        JSONObject dataJson = new JSONObject();
+        dataJson.put("split_type", splitType);
+        dataJson.put("skybox_type", skyboxType);
+//        dataJson.put("data_describe", dataDescribe);
+        dataJson.put("extras", null);
+        FileUtils.writeFile(path + File.separator + "data.json", dataJson.toString());
+    }
+
+    public static Map<String, String> getTypeString(String cameraType, String algorithm, String resolution){
+        Map<String, String> map = new HashMap<>();
+        String splitType = "";
+        String skyboxType = "";
+        String dataDescribe = "";
+        if(Integer.parseInt(cameraType) >= 4){
+            if("0".equals(resolution)){
+//            skyboxType = "SKYBOX_V4";  //tiles
+//            skyboxType = "SKYBOX_V6";    //high,low,4k
+                skyboxType = "SKYBOX_V7";    //high,low,2k
+            }else {
+                skyboxType = "SKYBOX_V1";
+            }
+            splitType = "SPLIT_V1";
+//            skyboxType = "SKYBOX_V4";  //tiles
+            dataDescribe = "double spherical";
+
+            if(Integer.parseInt(cameraType) == 5 ){
+                //新双目相机
+//              skyboxType = "SKYBOX_V9";
+                splitType = "SPLIT_V9";
+                skyboxType = "SKYBOX_V1";
+            }
+            if(Integer.parseInt(cameraType) == 6){
+                //小红屋新双目相机
+//                    skyboxType = "SKYBOX_V9";
+                splitType = "SPLIT_V3";
+                skyboxType = "SKYBOX_V7";
+            }
+
+            if(Integer.parseInt(cameraType) == 13){
+                //转台相机
+                skyboxType = "SKYBOX_V6";
+                splitType = "SPLIT_V12";
+            }
+
+            if(Integer.parseInt(cameraType) == 14){
+                //转台相机
+                log.info("激光转台相机调用算法");
+                skyboxType = "SKYBOX_V11";
+                splitType = "SPLIT_V14";
+            }
+
+        }else {
+            if("sfm".equals(algorithm)){
+                splitType = "SPLIT_V2";
+                skyboxType = "SKYBOX_V1";
+                dataDescribe = "old sfm";
+            }else {
+                splitType = "SPLIT_V3";
+                skyboxType = "SKYBOX_V1";
+                dataDescribe = "old slam";
+            }
+        }
+        map.put("splitType", splitType);
+        map.put("skyboxType", skyboxType);
+        map.put("dataDescribe", dataDescribe);
+        return map;
+    }
+}

+ 91 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/utils/DingDingUtils.java

@@ -0,0 +1,91 @@
+package com.fdkankan.modeling.utils;
+
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.DingTalkClient;
+import com.dingtalk.api.request.OapiRobotSendRequest;
+import com.dingtalk.api.response.OapiRobotSendResponse;
+import com.fdkankan.common.utils.Base64Converter;
+import com.fdkankan.modeling.constants.SysConstants;
+import com.taobao.api.ApiException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+
+@Component
+public class DingDingUtils {
+
+    private static final Logger log = LoggerFactory.getLogger(DingDingUtils.class);
+
+    private static String environment;
+
+    private static String token;
+
+    private static String secret="SECca5af660ed882a67d8bda469095bf8454831528bd25bc7b1a3ff5f686109b9e5";
+
+    @Value("${environment:dev}")
+    public void setEnvironment(String environment){
+        DingDingUtils.environment = environment;
+    }
+
+    @Value("${dingtalk.token:e712c41d917b303e21c1550ad9966b33dad874043f2f73fb347dce67a0a201bc}")
+    public void setToken(String token) {
+        DingDingUtils.token = token;
+    }
+
+    @Value("${dingtalk.secret:SECca5af660ed882a67d8bda469095bf8454831528bd25bc7b1a3ff5f686109b9e5}")
+    public void setSign(String secret) {
+        DingDingUtils.secret = secret;
+    }
+
+    private static String msgPattern = "**环境**: %s\n\n" +
+            "**服务器名称**: %s\n\n" +
+            "**失败原因**: %s\n\n" +
+            "**num**: %s\n\n" +
+            "**server-path**: %s\n\n" +
+            "**algorithm-log**: [https://4dkk.4dage.com/build_log/%s/console.log](https://4dkk.4dage.com/build_log/%s/console.log)";
+
+
+    public static void sendMsgToDingRobot(String reason,String serverPath,String num) throws ApiException, UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
+        String content = String.format(msgPattern,environment, SysConstants.hostName,reason,num,serverPath,num,num);
+        sendMsgToDingRobot(content);
+    }
+
+    public static void sendMsgToDingRobot(String content) throws ApiException, UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
+        Long timestamp = System.currentTimeMillis();
+        String sign = getSign(timestamp);
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/robot/send?" +
+                "access_token="+token +
+                "&timestamp=".concat(String.valueOf(timestamp)).concat("&sign=").concat(sign));
+        OapiRobotSendRequest request = new OapiRobotSendRequest();
+        request.setMsgtype("actionCard");
+        OapiRobotSendRequest.Actioncard actioncard = new OapiRobotSendRequest.Actioncard();
+        actioncard.setTitle("场景计算失败");
+        actioncard.setText(content);
+        request.setActionCard(actioncard);
+        OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
+        at.setAtMobiles(new ArrayList<>(0));
+        // isAtAll类型如果不为Boolean,请升级至最新SDK
+        at.setIsAtAll(true);
+        request.setAt(at);
+        OapiRobotSendResponse re = client.execute(request);
+        System.out.println(re.getBody());
+    }
+
+    public static String getSign(Long timestamp) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
+        String stringToSign = timestamp + "\n" + secret;
+        Mac mac = Mac.getInstance("HmacSHA256");
+        mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
+        byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
+        System.out.println(new String(signData));
+        return URLEncoder.encode(Base64Converter.encode(signData));
+    }
+}

+ 46 - 0
4dkankan-center-modeling/src/main/java/com/fdkankan/modeling/utils/PushMsgUtil.java

@@ -0,0 +1,46 @@
+package com.fdkankan.modeling.utils;
+
+import com.fdkankan.common.constant.ConstantFilePath;
+import com.google.auth.oauth2.GoogleCredentials;
+import com.google.firebase.FirebaseApp;
+import com.google.firebase.FirebaseOptions;
+import com.google.firebase.messaging.FirebaseMessaging;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.FileInputStream;
+
+/**
+ * Created by Hb_zzZ on 2020/7/27.
+ */
+@Slf4j
+public class PushMsgUtil {
+
+    /**
+     * 海外谷歌推送
+     */
+    public static void googlePushMsg(String token, String title, String text, String url){
+        try{
+            FileInputStream refreshToken = new FileInputStream(ConstantFilePath.BASE_PATH + "/refreshToken.json");
+
+            FirebaseOptions options = new FirebaseOptions.Builder()
+                    .setCredentials(GoogleCredentials.fromStream(refreshToken))
+                    .setDatabaseUrl("https://dkankan-pro.firebaseio.com")
+                    .build();
+
+            FirebaseApp.initializeApp(options);
+
+            com.google.firebase.messaging.Message message = com.google.firebase.messaging.Message.builder()
+                    .putData("titile", title)
+                    .putData("text", text)
+                    .putData("url", url)
+                    .setNotification(new com.google.firebase.messaging.Notification(title, text))
+                    .setToken(token)
+                    .build();
+            String response = FirebaseMessaging.getInstance().send(message);
+            log.info("Successfully sent message: " + response);
+        }catch (Exception e ){
+            e.printStackTrace();
+        }
+
+    }
+}

+ 0 - 1
4dkankan-center-modeling/src/main/resources/application.properties

@@ -1 +0,0 @@
-

+ 20 - 0
4dkankan-center-modeling/src/main/resources/bootstrap.yml

@@ -0,0 +1,20 @@
+spring:
+  application:
+    name: 4dkankan-center-modeling
+  cloud:
+    nacos:
+      config:
+        server-addr: 192.168.0.47:8848
+        file-extension: yaml
+        namespace: 4dkankan-dev
+        extension-configs[0]:
+          data-id: redis-config.yaml
+          group: DEFAULT_GROUP
+          refresh: true
+        extension-configs[1]:
+          data-id: common-mq-config.yaml
+          group: DEFAULT_GROUP
+          refresh: true
+      discovery:
+        server-addr: 192.168.0.47:8848
+        namespace: 4dkankan-dev

+ 231 - 0
4dkankan-center-modeling/src/main/resources/logback-spring.xml

@@ -0,0 +1,231 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
+<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
+<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
+<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
+<configuration scan="true" scanPeriod="10 seconds">
+
+	<contextName>logback</contextName>
+	<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
+	<property name="log.path" value="/home/logs/4dkankan_center_modeling" />
+
+	<!-- 彩色日志 -->
+	<!-- 彩色日志依赖的渲染类 -->
+	<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
+	<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
+	<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
+	<!-- 彩色日志格式 -->
+	<property name="CONSOLE_LOG_PATTERN"
+		value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
+
+	<!--输出到控制台 -->
+	<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+		<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息 -->
+		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+			<level>info</level>
+		</filter>
+		<encoder>
+			<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
+			<!-- 设置字符集 -->
+			<charset>UTF-8</charset>
+		</encoder>
+	</appender>
+	<!--输出到文件 -->
+
+	<!-- 时间滚动输出 level为 DEBUG 日志 -->
+	<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文件的路径及文件名 -->
+		<file>${log.path}/log_debug.log</file>
+		<!--日志文件输出格式 -->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+			<charset>UTF-8</charset> <!-- 设置字符集 -->
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<!-- 日志归档 -->
+			<fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log
+			</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文件保留天数 -->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文件只记录debug级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>debug</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+
+	<!-- 时间滚动输出 level为 INFO 日志 -->
+	<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文件的路径及文件名 -->
+		<file>${log.path}/log_info.log</file>
+		<!--日志文件输出格式 -->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+			<charset>UTF-8</charset>
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<!-- 每天日志归档路径以及格式 -->
+			<fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log
+			</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文件保留天数 -->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文件只记录info级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>info</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+
+	<!-- 时间滚动输出 level为 WARN 日志 -->
+	<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文件的路径及文件名 -->
+		<file>${log.path}/log_warn.log</file>
+		<!--日志文件输出格式 -->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+			<charset>UTF-8</charset> <!-- 此处设置字符集 -->
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log
+			</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文件保留天数 -->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文件只记录warn级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>warn</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+
+
+	<!-- 时间滚动输出 level为 ERROR 日志 -->
+	<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文件的路径及文件名 -->
+		<file>${log.path}/log_error.log</file>
+		<!--日志文件输出格式 -->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+			<charset>UTF-8</charset> <!-- 此处设置字符集 -->
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log
+			</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文件保留天数 -->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文件只记录ERROR级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>ERROR</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+	
+	<appender name="PROGRAM_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文件的路径及文件名 -->
+		<file>${log.path}/program/log_program.log</file>
+		<!--日志文件输出格式 -->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+			<charset>UTF-8</charset> <!-- 此处设置字符集 -->
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<fileNamePattern>${log.path}/program/log-program-%d{yyyy-MM-dd}.%i.log
+			</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文件保留天数 -->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文件只记录ERROR级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+	<logger name="programLog" level="INFO" additivity="true">
+        <appender-ref ref="PROGRAM_FILE"/>
+    </logger>
+
+	<appender name="VISIT_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文件的路径及文件名 -->
+		<file>${log.path}/visit/log_visit.log</file>
+		<!--日志文件输出格式 -->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+			<charset>UTF-8</charset> <!-- 此处设置字符集 -->
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<fileNamePattern>${log.path}/visit/log-visit-%d{yyyy-MM-dd}.%i.log
+			</fileNamePattern>
+
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文件保留天数 -->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文件只记录ERROR级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+	<logger name="visitLog" level="INFO" additivity="true">
+        <appender-ref ref="VISIT_FILE"/>
+    </logger>
+
+	<!-- <logger>用来设置某一个包或者具体的某一个类的日志打印级别、 以及指定<appender>。<logger>仅有一个name属性, 一个可选的level和一个可选的addtivity属性。 name:用来指定受此logger约束的某一个包或者具体的某一个类。 level:用来设置打印级别,大小写无关:TRACE, 
+		DEBUG, INFO, WARN, ERROR, ALL 和 OFF, 还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。 如果未设置此属性,那么当前logger将会继承上级的级别。 addtivity:是否向上级logger传递打印信息。默认是true。 -->
+	<!--<logger name="org.springframework.web" level="info"/> -->
+	<!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/> -->
+	<!-- 使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作: 第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息 第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别: -->
+	<!-- root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性 level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF, 不能设置为INHERITED或者同义词NULL。默认是DEBUG 可以包含零个或多个元素,标识这个appender将会添加到这个logger。 -->
+
+	<root level="info">
+		<appender-ref ref="CONSOLE" />
+		<appender-ref ref="DEBUG_FILE" />
+		<appender-ref ref="INFO_FILE" />
+		<appender-ref ref="WARN_FILE" />
+		<appender-ref ref="ERROR_FILE" />
+	</root>
+
+	<!--生产环境:输出到文件 -->
+	<!--<springProfile name="pro"> -->
+	<!--<root level="info"> -->
+	<!--<appender-ref ref="CONSOLE" /> -->
+	<!--<appender-ref ref="DEBUG_FILE" /> -->
+	<!--<appender-ref ref="INFO_FILE" /> -->
+	<!--<appender-ref ref="ERROR_FILE" /> -->
+	<!--<appender-ref ref="WARN_FILE" /> -->
+	<!--</root> -->
+	<!--</springProfile> -->
+
+</configuration>
+
+