Prechádzať zdrojové kódy

合并官网正式环境最新代码

tianboguang 2 rokov pred
rodič
commit
1473b5d90a

+ 5 - 0
src/main/java/com/fdkankan/contro/bean/SceneJsonBean.java

@@ -118,6 +118,11 @@ public class SceneJsonBean {
     private String sceneKind;
 
     /**
+     * dam,3dtiles
+     */
+    private String modelKind;
+
+    /**
      * 空间视频数据
      */
     private String boxVideos;

+ 2 - 2
src/main/java/com/fdkankan/contro/entity/Scene3dNum.java

@@ -41,7 +41,7 @@ public class Scene3dNum implements Serializable {
      * 记录的状态,A: 生效,I: 禁用
      */
     @TableField("code")
-    private String num;
+    private String code;
 
     /**
      * 更新时间
@@ -59,7 +59,7 @@ public class Scene3dNum implements Serializable {
      * A正常,I删除
      */
     @TableField("rec_status")
-    @TableLogic("A")
+    @TableLogic(value = "A", delval = "I")
     private String recStatus;
 
 

+ 81 - 0
src/main/java/com/fdkankan/contro/entity/SceneBuildProcessLog.java

@@ -0,0 +1,81 @@
+package com.fdkankan.contro.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 场景计算流程状态表
+ * </p>
+ *
+ * @author 
+ * @since 2023-01-28
+ */
+@Getter
+@Setter
+@TableName("t_scene_build_process_log")
+public class SceneBuildProcessLog implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 场景码
+     */
+    @TableField("num")
+    private String num;
+
+    /**
+     * 计算流程(pre-前置处理,call-计算,post-后置处理)
+     */
+    @TableField("process")
+    private String process;
+
+    /**
+     * mq消息队列名称
+     */
+    @TableField("queue_name")
+    private String queueName;
+
+    /**
+     * 处理状态(0-处理中,1-成功,2-失败)
+     */
+    @TableField("state")
+    private Integer state;
+
+    /**
+     * 失败原因
+     */
+    @TableField("reason")
+    private String reason;
+
+    /**
+     * 创建时间
+     */
+    @TableField("create_time")
+    private Date createTime;
+
+    /**
+     * 修改时间
+     */
+    @TableField("update_time")
+    private Date updateTime;
+
+    /**
+     * A-有效,I-无效
+     */
+    @TableField("rec_status")
+    @TableLogic(value = "A", delval = "I")
+    private String recStatus;
+
+
+}

+ 6 - 0
src/main/java/com/fdkankan/contro/entity/ScenePlus.java

@@ -92,6 +92,12 @@ public class ScenePlus implements Serializable {
     private Integer recommend;
 
     /**
+     * 是否有housetype文件(0-否,1-是)
+     */
+    @TableField("house_type")
+    private Integer houseType;
+
+    /**
      * 创建时间
      */
     @TableField("create_time")

+ 6 - 0
src/main/java/com/fdkankan/contro/entity/ScenePlusExt.java

@@ -125,6 +125,12 @@ public class ScenePlusExt implements Serializable {
     private String sceneKind;
 
     /**
+     * 算法模型类型(dam,3dtiles)
+     */
+    @TableField("model_kind")
+    private String modelKind;
+
+    /**
      * 计算耗时
      */
     @TableField("compute_time")

+ 18 - 0
src/main/java/com/fdkankan/contro/mapper/ISceneBuildProcessLogMapper.java

@@ -0,0 +1,18 @@
+package com.fdkankan.contro.mapper;
+
+import com.fdkankan.contro.entity.SceneBuildProcessLog;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 场景计算流程状态表 Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2023-01-28
+ */
+@Mapper
+public interface ISceneBuildProcessLogMapper extends BaseMapper<SceneBuildProcessLog> {
+
+}

+ 32 - 7
src/main/java/com/fdkankan/contro/mq/listener/AbstrackBuildSceneListener.java

@@ -1,8 +1,12 @@
 package com.fdkankan.contro.mq.listener;
 
+import cn.hutool.core.exceptions.ExceptionUtil;
 import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.common.constant.CommonOperStatus;
 import com.fdkankan.contro.constant.RedisConstants;
 import com.fdkankan.contro.mq.service.IBuildSceneService;
+import com.fdkankan.contro.service.ISceneBuildProcessLogService;
+import com.fdkankan.model.constants.SceneBuildProcessType;
 import com.fdkankan.rabbitmq.bean.BuildSceneCallMessage;
 import com.fdkankan.rabbitmq.bean.BuildSceneResultMqMessage;
 import com.fdkankan.redis.util.RedisLockUtil;
@@ -21,6 +25,8 @@ public class AbstrackBuildSceneListener implements IBuildSceneListener {
 
     @Autowired
     private RedisLockUtil redisLockUtil;
+    @Autowired
+    private ISceneBuildProcessLogService sceneBuildProcessLogService;
 
     @Override
     public void preHandle(Channel channel, String queueName, Message message, IBuildSceneService buildSceneService) throws IOException {
@@ -39,13 +45,23 @@ public class AbstrackBuildSceneListener implements IBuildSceneListener {
         String msg = new String(message.getBody(), StandardCharsets.UTF_8);
         log.info("开始准备场景计算资源,队列名:{},id:{},消息体:{}", queueName, messageId, msg);
         BuildSceneCallMessage buildSceneMessage = JSONObject.parseObject(msg, BuildSceneCallMessage.class);
-        if(ObjectUtils.isEmpty(buildSceneMessage.getBuildContext())){
-            buildSceneMessage.setBuildContext(new HashMap<>());
-        }
-        if(!ObjectUtils.isEmpty(buildSceneMessage.getSceneNum())){
-            buildSceneMessage.getBuildContext().put("sceneNum",buildSceneMessage.getSceneNum());
+        String num = buildSceneMessage.getSceneNum();
+        try {
+            if(ObjectUtils.isEmpty(buildSceneMessage.getBuildContext())){
+                buildSceneMessage.setBuildContext(new HashMap<>());
+            }
+            if(!ObjectUtils.isEmpty(buildSceneMessage.getSceneNum())){
+                buildSceneMessage.getBuildContext().put("sceneNum",buildSceneMessage.getSceneNum());
+            }
+            //记录日志
+            sceneBuildProcessLogService.clearSceneBuildProcessLog(num, SceneBuildProcessType.PRE.code(), queueName);
+            sceneBuildProcessLogService.saveSceneBuildProcessLog(num, SceneBuildProcessType.PRE.code(), queueName, CommonOperStatus.WAITING.code(), null);
+            buildSceneService.buildScenePre(buildSceneMessage);
+            sceneBuildProcessLogService.saveSceneBuildProcessLog(num, SceneBuildProcessType.PRE.code(), queueName, CommonOperStatus.SUCCESS.code(), null);
+        }catch (Exception e){
+            log.error("场景计算前置处理出错,num=" + num, e);
+            sceneBuildProcessLogService.saveSceneBuildProcessLog(num, SceneBuildProcessType.PRE.code(), queueName, CommonOperStatus.FAILD.code(), ExceptionUtil.stacktraceToString(e, 3000));
         }
-        buildSceneService.buildScenePre(buildSceneMessage);
         log.info("准备场景计算资源完成,队列名:{},id:{},消息体:{}", queueName, messageId, msg);
         channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
     }
@@ -67,7 +83,16 @@ public class AbstrackBuildSceneListener implements IBuildSceneListener {
         String msg = new String(message.getBody(), StandardCharsets.UTF_8);
         log.info("场景计算完成,开始处理场景计算结果,队列名:{},id:{},消息体:{}", queueName, messageId, msg);
         BuildSceneResultMqMessage buildSceneMessage = JSONObject.parseObject(msg, BuildSceneResultMqMessage.class);
-        buildSceneService.buildScenePost(buildSceneMessage);
+        String num = buildSceneMessage.getBuildContext().get("sceneNum").toString();
+        try {
+            sceneBuildProcessLogService.clearSceneBuildProcessLog(num, SceneBuildProcessType.POST.code(), queueName);
+            sceneBuildProcessLogService.saveSceneBuildProcessLog(num, SceneBuildProcessType.POST.code(), queueName, CommonOperStatus.WAITING.code(), null);
+            buildSceneService.buildScenePost(buildSceneMessage);
+            sceneBuildProcessLogService.saveSceneBuildProcessLog(num, SceneBuildProcessType.POST.code(), queueName, CommonOperStatus.SUCCESS.code(), null);
+        }catch (Exception e){
+            log.error("场景计算结果处理出错,num=" + num, e);
+            sceneBuildProcessLogService.saveSceneBuildProcessLog(num, SceneBuildProcessType.POST.code(), queueName, CommonOperStatus.FAILD.code(), ExceptionUtil.stacktraceToString(e, 3000));
+        }
         log.info("场景计算结果处理完成,队列名:{},id:{},消息体:{}", queueName, messageId, msg);
         channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
     }

+ 67 - 0
src/main/java/com/fdkankan/contro/mq/listener/BuildSceneProcessLogListener.java

@@ -0,0 +1,67 @@
+package com.fdkankan.contro.mq.listener;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.common.constant.CommonOperStatus;
+import com.fdkankan.common.constant.ModelingBuildStatus;
+import com.fdkankan.contro.service.ISceneBuildProcessLogService;
+import com.fdkankan.model.constants.SceneBuildProcessType;
+import com.fdkankan.rabbitmq.bean.BuildSceneProcessLogMessage;
+import com.rabbitmq.client.Channel;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.Queue;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.nio.charset.StandardCharsets;
+
+@Slf4j
+@Component
+public class BuildSceneProcessLogListener{
+
+    @Value("${queue.modeling.modeling-process-log}")
+    private String queueModelingProcessLog;
+    @Value("${queue.modeling.modeling-call}")
+    private String queueModelingCall;
+
+    @Autowired
+    private ISceneBuildProcessLogService sceneBuildProcessLogService;
+
+    /**
+     * 场景计算状态日志记录
+     * @param channel
+     * @param message
+     * @throws Exception
+     */
+    @RabbitListener(
+            queuesToDeclare = @Queue("${queue.modeling.modeling-process-log}")
+    )
+    public void buildScenePreHandler(Channel channel, Message message) throws Exception {
+        String msg = new String(message.getBody(), StandardCharsets.UTF_8);
+        BuildSceneProcessLogMessage buildSceneMessage = JSONObject.parseObject(msg, BuildSceneProcessLogMessage.class);
+        String num = buildSceneMessage.getNum();
+        try {
+            String reason = null;
+            int status = CommonOperStatus.SUCCESS.code();
+            int buildStatus = buildSceneMessage.getBuildStatus();
+            //新的计算开始,需要将之前的记录置为失效
+            if(buildStatus == ModelingBuildStatus.CALCULATING.code()){
+                sceneBuildProcessLogService.clearSceneBuildProcessLog(num, SceneBuildProcessType.CALL.code(),queueModelingCall);
+                status = CommonOperStatus.WAITING.code();
+            }else{
+                if(buildStatus != ModelingBuildStatus.SUCCESS.code()){
+                    status = CommonOperStatus.FAILD.code();
+                    reason = ModelingBuildStatus.get(buildStatus).message();
+                }
+            }
+            sceneBuildProcessLogService.saveSceneBuildProcessLog(num, SceneBuildProcessType.CALL.code(), queueModelingCall, status, reason);
+        }catch (Exception e){
+            log.error("场景计算流程状态日志记录出错, num="+num, e);
+        }finally {
+            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+        }
+    }
+
+}

+ 1 - 1
src/main/java/com/fdkankan/contro/mq/service/IBuildSceneService.java

@@ -13,7 +13,7 @@ import com.fdkankan.rabbitmq.bean.BuildSceneResultMqMessage;
  **/
 public interface IBuildSceneService {
 
-    void buildScenePre(BuildSceneCallMessage message);
+    void buildScenePre(BuildSceneCallMessage message) throws Exception;
 
     void downLoadSource(BuildSceneCallMessage buildSceneMqMessage, String path) throws Exception;
 

+ 103 - 62
src/main/java/com/fdkankan/contro/mq/service/impl/BuildSceneServiceImpl.java

@@ -2,9 +2,11 @@ package com.fdkankan.contro.mq.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.exceptions.ExceptionUtil;
 import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.io.file.FileNameUtil;
 import cn.hutool.core.util.StrUtil;
+import cn.hutool.core.util.ZipUtil;
 import cn.hutool.extra.qrcode.QrCodeUtil;
 import cn.hutool.extra.qrcode.QrConfig;
 import cn.hutool.http.HttpUtil;
@@ -21,9 +23,11 @@ import com.fdkankan.contro.mq.service.IBuildSceneService;
 import com.fdkankan.contro.service.*;
 import com.fdkankan.contro.vo.SceneEditControlsVO;
 import com.fdkankan.fyun.config.FYunFileConfig;
+import com.fdkankan.fyun.constant.FYunTypeEnum;
 import com.fdkankan.fyun.face.FYunFileServiceInterface;
 import com.fdkankan.model.constants.ConstantFileName;
 import com.fdkankan.model.constants.ConstantFilePath;
+import com.fdkankan.model.constants.SceneBuildProcessType;
 import com.fdkankan.model.constants.UploadFilePath;
 import com.fdkankan.model.enums.ModelTypeEnums;
 import com.fdkankan.model.utils.CreateHouseJsonUtil;
@@ -66,9 +70,12 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
     @Value("${queue.modeling.single.modeling-call}")
     private String singleModelingCall;
 
-    @Value("${model.type:tile}")
+    @Value("${model.type:#{null}}")
     private String modelType;
 
+    @Value("${model.modelKind:3dtiles}")
+    private String modelKind;
+
     @Autowired
     private RabbitMqProducer mqProducer;
 
@@ -99,10 +106,13 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
 
     @Autowired
     private ICompanyService companyService;
+    @Autowired
+    private ISceneAsynOperLogService sceneAsynOperLogService;
 
     @Override
-    public void buildScenePre(BuildSceneCallMessage message) {
+    public void buildScenePre(BuildSceneCallMessage message) throws Exception{
         boolean success = false;
+        String num = message.getSceneNum();
         try {
             //重新计算时需要删除文件夹,否知使用缓存
             if(new File(message.getPath() + File.separator + "results").exists()){
@@ -152,7 +162,8 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
             log.info("场景计算资源准备结束,场景码:{}", message.getSceneNum());
 
         }catch (Exception e){
-            log.error("场景计算前置处理出错", e);
+            log.error("场景计算前置处理出错,num"+num, e);
+            throw e;
         }finally {
             //如果前置处理失败,发送钉钉消息
             if(!success){
@@ -219,8 +230,6 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
             }
             scenePlus.setUpdateTime(new Date());
             scenePlus.setSceneStatus(SceneStatus.NO_DISPLAY.code());
-            scenePlusService.updateById(scenePlus);
-
 
             Integer videoVersion = fdageData.getInteger("videoVersion");
             //读取计算结果文件生成videosJson
@@ -239,10 +248,32 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
             //上传全景图俯视图
             this.uploadFloorCad(path, sceneCode, uploadFiles);
 
-            //上传文件
             log.info("开始上传场景计算结果数据,num:{}", sceneCode);
+            //由于3dtiles算法mesh文件发生变化,所以这里需要先清除一下oss的mesh目录,避免存在旧算法obj文件
+            fYunFileService.deleteFolder(String.format(UploadFilePath.DATA_VIEW_PATH, sceneCode) + "mesh");
+            //上传文件
             fYunFileService.uploadMulFiles(uploadFiles);
 
+            Map<String,String> damFileHeaders = new HashMap<>();
+            damFileHeaders.put("Content-Encoding","gzip");
+            if (!ObjectUtils.isEmpty(cameraType) && !cameraType.equals(14)) {
+                if (!fYunFileService.getFyunType().equals(FYunTypeEnum.LOCAL.code())) {
+                    // dam 文件设置请求头
+                    uploadFiles.entrySet().stream().filter(entry -> FileNameUtil.extName(entry.getKey()).equals("dam"))
+                        .forEach(entry -> {
+                            if (!new File(entry.getKey()).exists()) {
+                                log.error("文件不存在,不予gzip压缩,文件路径:{}", entry.getKey());
+                                return;
+                            }
+                            // gzip压缩
+                            FileUtil.writeBytes(ZipUtil.gzip(new File(entry.getKey())), entry.getKey() + ".gzip");
+                            // 重命名
+                            FileUtil.rename(new File(entry.getKey() + ".gzip"), entry.getKey(), true);
+                            fYunFileService.uploadFile(entry.getKey(), entry.getValue(), damFileHeaders);
+                        });
+                }
+            }
+
             //拷贝部分文件到编辑目录,用于用户编辑
             this.copyToEditDir(sceneCode);
 
@@ -250,16 +281,18 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
             this.cachePanorama(path, sceneCode);
 
             //生成houseTypejson并上传
-            uploadFiles.entrySet().stream().filter(entry-> FileNameUtil.getName(entry.getKey()).equals("floorplan_cad.json"))
-                    .forEach(entry-> uploadHouseTypeJson(sceneCode,entry.getKey()));
-
-            //写scene.json
+            boolean existHouseType = this.uploadHouseTypeJson(sceneCode, scenePlusExt.getDataSource());
+            scenePlus.setHouseType(existHouseType ? CommonStatus.YES.code().intValue() : CommonStatus.NO.code().intValue());
 
+            //重置异步操作记录
+            this.removeSceneAsynOperLog(sceneCode);
 
             log.info("生成scene.json上传oss并设置缓存,num:{}", sceneCode);
             CameraDetail cameraDetail = cameraDetailService.getByCameraId(scenePlus.getCameraId());
             Company company = !ObjectUtils.isEmpty(cameraDetail.getCompanyId()) ? companyService.getById(cameraDetail.getCompanyId()) : null;
 
+
+            //写scene.json
             this.writeSceneJson(sceneCode, videosJson,sceneEditInfo, sceneEditInfoExt, sceneEditControls, scenePlus,scenePlusExt,company);
 
             String qrLogo = !ObjectUtils.isEmpty(company) && !ObjectUtils.isEmpty(company.getQrLogo()) ? company.getQrLogo() : null;
@@ -271,16 +304,39 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
             //计算成功,通知APP
             Integer pushChannel = fdageData.getInteger("pushChannel");
             String pushToken = fdageData.getString("pushToken");
-            this.pushMsgToApp(pushChannel,pushToken, cameraType, scenePlus.getTitle(), scenePlusExt.getWebSite());
+
+            //更新场景主表
+            scenePlusService.updateById(scenePlus);
 
             CreateObjUtil.deleteFile(path.replace(ConstantFilePath.BUILD_MODEL_PATH, "/") + "/capture");
 
             log.info("场景计算结果处理结束,场景码:{}", sceneCode);
 
         }catch (Exception e){
-            e.printStackTrace();
+            log.error("场景计算结果处理出错,num"+sceneCode, e);
             buildSceneDTService.handBaseFail("场景计算结果处理出错!", message.getPath(), sceneCode, "计算控制服务器");
+            throw e;
+        }
+    }
+
+    private void removeSceneAsynOperLog(String num){
+        List<SceneAsynOperLog> list = sceneAsynOperLogService.list(new LambdaQueryWrapper<SceneAsynOperLog>().eq(SceneAsynOperLog::getNum, num));
+        if(CollUtil.isEmpty(list)){
+            return;
         }
+        //删除数据库记录
+        List<Long> deleteIdList = list.parallelStream().map(item -> item.getId()).collect(Collectors.toList());
+        sceneAsynOperLogService.removeByIds(deleteIdList);
+
+        list.parallelStream().forEach(item -> {
+            if(StrUtil.isNotEmpty(item.getUrl())){
+                try {
+                    fYunFileService.deleteFile(item.getUrl());
+                } catch (IOException e) {
+                    log.warn("删除oss全景图下载压缩包失败,key:{}", item.getUrl());
+                }
+            }
+        });
     }
 
     private void cachePanorama(String dataSource, String num){
@@ -369,9 +425,8 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
             }
         }
 
-
-        if ((fdageData.containsKey("exportMeshObj") && fdageData.getIntValue("exportMeshObj") == 1)
-                || (!ObjectUtils.isEmpty(cameraType) && (!cameraType.equals(14)))) {
+        //exportMeshObj这个是字段由app写入的
+        if (!ObjectUtils.isEmpty(cameraType) && cameraType != 14) {
             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");
@@ -379,13 +434,28 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
             map.put(path + File.separator + "results" + File.separator + ConstantFileName.modelUUID + "_50k.dam", imagesPath + ConstantFileName.modelUUID + "_50k.dam");
         }
 
+        if(this.modelKind.equals(ModelKind.THREE_D_TILE.code())
+                && (!ObjectUtils.isEmpty(cameraType) && cameraType == 14 )//是激光场景
+                && (fdageData.containsKey("exportMeshObj") && fdageData.getIntValue("exportMeshObj") == 1)//选择生成obj
+        ){
+            List<String> list = FileUtils.list(new File(path + File.separator + "results" + File.separator + ModelKind.THREE_D_TILE.code()));
+            if(CollUtil.isEmpty(list)){
+                log.error("3dtiles目录异常,3dtiles地址:{}", new File(path + File.separator + "results" + File.separator + ModelKind.THREE_D_TILE.code()));
+                throw new Exception("3dtiles目录异常");
+            }
+            list.stream().forEach(str->{
+                map.put(str, str.replace(path + File.separator + "results" + File.separator, imagesPath));
+            });
+        }
+
         CreateObjUtil.convertTxtToVisionmodeldata(resultsPath + "vision.txt", resultsPath + "vision.modeldata");
         map.put(resultsPath + "vision.txt", imagesPath + "vision.txt");
         map.put(resultsPath + "vision.modeldata", imagesPath + "vision.modeldata");
 
         log.info("数据转换完成:" + projectNum);
-
-        FileUtil.touch("/mnt/4Dkankan/scene/data" + File.separator + "data" + projectNum);
+        if(!new File("/mnt/4Dkankan/scene/data" + File.separator + "data" + projectNum).exists()){
+            FileUtil.mkdir("/mnt/4Dkankan/scene/data" + File.separator + "data" + projectNum);
+        }
         map.put(resultsPath + "floorplan.json", dataViewPath + "floor.json");
         map.put(resultsPath + "floorplan_cad.json", dataViewPath + "floorplan_cad.json");
         map.put(path + File.separator + "capture/stitch_params.txt", dataViewPath + "stitch_params.txt");
@@ -443,6 +513,7 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
         sceneJson.setImgVersion(sceneEditInfo.getImgVersion());
         sceneJson.setSceneFrom(scenePlusExt.getSceneFrom());
         sceneJson.setSceneKind(scenePlusExt.getSceneKind());
+        sceneJson.setModelKind(scenePlusExt.getModelKind());
         sceneJson.setVideos(JSON.toJSONString(videosJson));
         sceneJson.setPayStatus(scenePlus.getPayStatus());
 
@@ -513,6 +584,8 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
         String outPathZh = ConstantFilePath.BASE_PATH + File.separator + "sceneQRcode/"+ num +".png";
         String outPathEn = ConstantFilePath.BASE_PATH + File.separator + "sceneQRcode/"+ num +"_en.png";
         QrConfig qrConfig = QrConfig.create();
+        qrConfig.setWidth(512);
+        qrConfig.setHeight(512);
         if(!ObjectUtils.isEmpty(localLogoPath)){
             qrConfig.setImg(localLogoPath);
         }
@@ -527,10 +600,6 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
         }
     }
 
-    private void pushMsgToApp(Integer pushChannel, String pushToken, int cameraType, String sceneName, String webSite){
-        log.info("推送消息,渠道是 {}, 手机token是 {}", pushChannel, pushToken);
-    }
-
     private void copyToEditDir(String num) throws IOException {
 
         String editImagesPath = String.format(UploadFilePath.IMG_EDIT_PATH, num);
@@ -636,42 +705,6 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
         return uploadFile.keySet().stream().map(File::new).filter(File::exists).mapToLong(File::length).sum();
     }
 
-    private void sealScene(Long scenePlusId){
-        scenePlusService.update(
-            new LambdaUpdateWrapper<ScenePlus>()
-                .set(ScenePlus::getPayStatus, PayStatus.NO_CAPACITY.code())
-                .eq(ScenePlus::getId, scenePlusId));
-    }
-
-    /**
-     * <p>
-     双目场景更新数据库
-     * </p>
-     * @author dengsixing
-     * @date 2022/3/21
-     * @param num
-     * @param space
-     **/
-    private void updateDb4Sm(String num, long space){
-        List<ScenePlus> ScenePlusList = scenePlusService.list(
-            new LambdaQueryWrapper<ScenePlus>().select(ScenePlus::getId).eq(ScenePlus::getNum, num));
-
-        if(CollUtil.isEmpty(ScenePlusList)){
-            return ;
-        }
-
-        List<Long> sceneIds = ScenePlusList.stream().map(ScenePlus::getId).collect(Collectors.toList());
-
-        //更新场景创建时间
-        scenePlusService.update(new LambdaUpdateWrapper<ScenePlus>().in(ScenePlus::getId, sceneIds)
-            .set(ScenePlus::getSceneStatus, SceneStatus.NO_DISPLAY.code()));
-
-        //更新使用容量
-        scenePlusExtService.update(new LambdaUpdateWrapper<ScenePlusExt>().in(ScenePlusExt::getPlusId, sceneIds)
-                .set(ScenePlusExt::getSpace, space)
-                .set(ScenePlusExt::getAlgorithmTime, Calendar.getInstance().getTime()));
-    }
-
     private void updateDbPlus(int sceneSource,Long space,String videosJson, Long computeTime,boolean isObj,ScenePlusExt scenePlusExt){
 
         scenePlusExt.setSpace(space);
@@ -705,6 +738,7 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
 
         String sceneKind = scenePlusExt.getSceneScheme() == 3 ? SceneKind.FACE.code():SceneKind.TILES.code();
         scenePlusExt.setSceneKind(sceneKind);
+//        scenePlusExt.setModelKind(modelKind);
 
         scenePlusExtService.updateById(scenePlusExt);
     }
@@ -731,6 +765,7 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
             sceneEditInfoExt = sceneEditInfoExtService.getByEditInfoId(sceneEditInfo.getId());
             sceneEditInfo.setVersion(sceneEditInfo.getVersion() + 1);
             sceneEditInfo.setImgVersion(sceneEditInfo.getImgVersion() + 1);
+            sceneEditInfo.setIsUploadObj(CommonStatus.NO.code());
             sceneEditInfoService.updateById(sceneEditInfo);
         }
         if(sceneEditControls == null){
@@ -747,15 +782,21 @@ public class BuildSceneServiceImpl implements IBuildSceneService {
         return new Object[]{sceneEditInfo, sceneEditInfoExt, sceneEditControls};
     }
 
-    public void uploadHouseTypeJson(String num, String floorPlanCardFilePath) {
+    public boolean uploadHouseTypeJson(String num, String dataSource) {
+        String floorPlanCardFilePath = dataSource + File.separator + "results/floorplan_cad.json";
         if (!new File(floorPlanCardFilePath).exists()) {
-            log.error("floorplan_cad.json 文件不存在,文件路径:{}", floorPlanCardFilePath);
-            return;
+            log.warn("floorplan_cad.json 文件不存在,文件路径:{}", floorPlanCardFilePath);
+            return false;
         }
         JSONObject json = CreateHouseJsonUtil.createHouseTypeJsonByCad(floorPlanCardFilePath);
-        String hourseTypeJsonPath = String.format(UploadFilePath.DATA_VIEW_PATH, num) + "houseType.json";
+        if(Objects.isNull(json)){
+            return false;
+        }
+        String hourseTypeJsonPath = String.format(UploadFilePath.USER_VIEW_PATH, num) + "houseType.json";
         fYunFileService.uploadFile(json.toJSONString().getBytes(), hourseTypeJsonPath);
-        hourseTypeJsonPath = String.format(UploadFilePath.DATA_EDIT_PATH, num) + "houseType.json";
+        hourseTypeJsonPath = String.format(UploadFilePath.USER_EDIT_PATH, num) + "houseType.json";
         fYunFileService.uploadFile(json.toJSONString().getBytes(), hourseTypeJsonPath);
+
+        return true;
     }
 }

+ 3 - 1
src/main/java/com/fdkankan/contro/service/IScene3dNumService.java

@@ -23,7 +23,9 @@ public interface IScene3dNumService extends IService<Scene3dNum> {
      * 从码池中取出一个场景码
      * @return
      */
-    String generateSceneNum(Integer cameraType);
+    String generateSceneNum(Integer cameraType) throws Exception;
+
+    void generateSceneNumHandler();
 
     /**
      * 批量生成场景码并放入码池

+ 20 - 0
src/main/java/com/fdkankan/contro/service/ISceneBuildProcessLogService.java

@@ -0,0 +1,20 @@
+package com.fdkankan.contro.service;
+
+import com.fdkankan.contro.entity.SceneBuildProcessLog;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 场景计算流程状态表 服务类
+ * </p>
+ *
+ * @author 
+ * @since 2023-01-28
+ */
+public interface ISceneBuildProcessLogService extends IService<SceneBuildProcessLog> {
+
+    public void clearSceneBuildProcessLog(String num, String process, String queueName);
+
+    public void saveSceneBuildProcessLog(String num, String process, String queueName, int status, String reason);
+
+}

+ 62 - 63
src/main/java/com/fdkankan/contro/service/impl/Scene3dNumServiceImpl.java

@@ -1,11 +1,9 @@
 package com.fdkankan.contro.service.impl;
 
-import cn.hutool.core.util.StrUtil;
+import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fdkankan.common.constant.CommonStatus;
-import com.fdkankan.common.constant.ErrorCode;
-import com.fdkankan.common.exception.BusinessException;
 import com.fdkankan.common.util.RandomUtil;
 import com.fdkankan.contro.entity.Scene3dNum;
 import com.fdkankan.contro.enums.CameraTypeEnum;
@@ -18,14 +16,13 @@ import com.fdkankan.redis.util.RedisUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
 import org.springframework.stereotype.Service;
-import org.springframework.util.CollectionUtils;
 
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
-import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
 
 /**
@@ -36,6 +33,7 @@ import java.util.stream.Collectors;
  * @author dengsixing
  * @since 2021-12-23
  */
+@RefreshScope
 @Slf4j
 @Service
 public class Scene3dNumServiceImpl extends ServiceImpl<IScene3dNumMapper, Scene3dNum> implements IScene3dNumService {
@@ -47,54 +45,63 @@ public class Scene3dNumServiceImpl extends ServiceImpl<IScene3dNumMapper, Scene3
 
     @Value("${scene.num.cachePageSize:500}")
     private int cachePageSize;
-    @Value("${scene.num.threshold:10000}")
+    @Value("${scene.num.threshold:1000}")
     private int threshold;
-    @Value("${scene.num.prefix:V4-}")
+    @Value("${scene.num.prefix}")
     private String numPrefix;
     @Value("${scene.num.batchSize:100}")
     private int batchSize;
+    @Value("${main.url}")
+    private String mainUrl;
+
 
     @Override
-    public String generateSceneNum(Integer cameraType){
+    public String generateSceneNum(Integer cameraType) throws Exception {
         // 从缓存中获取
         String sceneNum = redisUtil.lLeftPop(RedisKey.FDKANKAN_SCENE_NUMS);
         if(Objects.nonNull(sceneNum)){
             return addPrefix(sceneNum,cameraType);
         }
+        //为了防止场景量暴增导致定时任务来还不急处理,如果上面redis获取不到,需要调用一下生成场景码方法
+        log.warn("定时任务没有生成足够的场景码,此处实时调用批量生成场景码程序");
+        this.generateSceneNumHandler();
+        Thread.sleep(5000L);
+        // 从缓存中获取
+        sceneNum = redisUtil.lLeftPop(RedisKey.FDKANKAN_SCENE_NUMS);
+        if(Objects.isNull(sceneNum)){
+            throw new Exception("场景计算获取场景码失败");
+        }
+        return addPrefix(sceneNum,cameraType);
+    }
+
+    @Override
+    public void generateSceneNumHandler() {
+        boolean lock =  redisLockUtil.lock(RedisLockKey.LOCK_FDKANKAN_SCENE_NUMS, RedisKey.EXPIRE_TIME_30_MINUTE);
+        if(!lock){
+            return;
+        }
         // 分布式加锁
-        boolean lock =  redisLockUtil.lock(RedisLockKey.LOCK_FDKANKAN_SCENE_NUMS, RedisKey.EXPIRE_TIME_10_MINUTE);
-        if (lock) {
-            try {
-                log.info("开始加载场景码缓存");
-                List<String> nums = this.findSceneNum(cachePageSize);
-                if(CollectionUtils.isEmpty(nums)){
-                    batchCreateSceneNum(true);
-                    nums = this.findSceneNum(cachePageSize);
-                }else{
-                    CompletableFuture.runAsync(() -> batchCreateSceneNum(false));
-                }
+        try {
+            //检查mysql码池中是否有足够的未使用场景,不够时,需要创建一批
+            batchCreateSceneNum(false);
+
+            //检查redis中场景码是否少于指定缓存数量,少于时,需要从码池中获取
+            long redisCnt = redisUtil.lGetSize(RedisKey.FDKANKAN_SCENE_NUMS);
+            if(redisCnt >= cachePageSize){
+                return;
+            }
+            log.info("开始加载场景码缓存");
+            List<String> nums = this.findSceneNum(cachePageSize);
+            if(CollUtil.isNotEmpty(nums)){
                 redisUtil.lRightPushAll(RedisKey.FDKANKAN_SCENE_NUMS, nums);
                 this.updateUsedStatus(nums);
-                log.info("场景码加载缓存完成");
-            } catch (Exception e) {
-                log.error("场景码加载缓存失败", e);
-            } finally {
-                redisLockUtil.unlockLua(RedisLockKey.LOCK_FDKANKAN_SCENE_NUMS);
-            }
-        }else{
-            // 等待2秒加载缓存
-            try {
-                Thread.sleep(2000);
-            } catch (InterruptedException e) {
-                log.error("场景码加载缓存失败", e);
             }
+            log.info("场景码加载缓存完成");
+        } catch (Exception e) {
+            log.error("场景码加载缓存失败", e);
+        } finally {
+            redisLockUtil.unlockLua(RedisLockKey.LOCK_FDKANKAN_SCENE_NUMS);
         }
-        sceneNum = redisUtil.lLeftPop(RedisKey.FDKANKAN_SCENE_NUMS);
-        if(StrUtil.isEmpty(sceneNum)){
-            log.error("场景码加载失败");
-            throw new BusinessException(ErrorCode.FAILURE_CODE_5053);
-        }
-        return addPrefix(sceneNum,cameraType);
     }
 
     private  static  String addPrefix( String num,Integer cameraType){
@@ -106,34 +113,26 @@ public class Scene3dNumServiceImpl extends ServiceImpl<IScene3dNumMapper, Scene3
 
     @Override
     public void batchCreateSceneNum(boolean force) {
-        String lockKey = String.format(RedisLockKey.LOCK_BATCH_CREATE_NUM);
-        boolean lock = redisLockUtil.lock(lockKey, RedisKey.EXPIRE_TIME_10_MINUTE);
-        if(!lock){
-            return;
-        }
-        try {
-            if (!force) {
-                long count = this.count(new LambdaQueryWrapper<Scene3dNum>().eq(Scene3dNum::getUsed, CommonStatus.NO.code()));
-                if (count > threshold) {
-                    return;
-                }
+        if (!force) {
+            long count = this.count(new LambdaQueryWrapper<Scene3dNum>().eq(Scene3dNum::getUsed, CommonStatus.NO.code()));
+            if (count > threshold) {
+                return;
             }
-            int batchCnt = threshold / batchSize + (threshold % batchSize > 0 ? 1 : 0);
-            for (int i = 0; i < batchCnt; i++){
-                Set<String> numSet = this.turnCreateSceneNum(batchSize);
-                List<Scene3dNum> scene3dNumList = numSet.parallelStream().map(num -> {
-                    Scene3dNum scene3dNum = new Scene3dNum();
-                    scene3dNum.setNum(num);
-                    return scene3dNum;
-                }).collect(Collectors.toList());
-                try{
-                    this.saveBatch(scene3dNumList);
-                }catch (Exception e){
-                    log.error("场景码插入异常!",e);
-                }
+        }
+        int batchCnt = threshold / batchSize + (threshold % batchSize > 0 ? 1 : 0);//批次数
+        for (int i = 0; i < batchCnt; i++){//分批生成,每批次batchSize个
+            Set<String> numSet = this.turnCreateSceneNum(batchSize);
+            List<Scene3dNum> scene3dNumList = numSet.parallelStream().map(num -> {
+                Scene3dNum scene3dNum = new Scene3dNum();
+                scene3dNum.setCode(num);
+                return scene3dNum;
+            }).collect(Collectors.toList());
+            try{
+                this.saveBatch(scene3dNumList);
+            }catch (Exception e){
+                log.error("场景码插入异常!");
+                e.printStackTrace();
             }
-        }finally {
-            redisLockUtil.unlockLua(lockKey);
         }
     }
 

+ 50 - 0
src/main/java/com/fdkankan/contro/service/impl/SceneBuildProcessLogServiceImpl.java

@@ -0,0 +1,50 @@
+package com.fdkankan.contro.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.fdkankan.contro.entity.SceneBuildProcessLog;
+import com.fdkankan.contro.mapper.ISceneBuildProcessLogMapper;
+import com.fdkankan.contro.service.ISceneBuildProcessLogService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.Objects;
+
+/**
+ * <p>
+ * 场景计算流程状态表 服务实现类
+ * </p>
+ *
+ * @author 
+ * @since 2023-01-28
+ */
+@Service
+public class SceneBuildProcessLogServiceImpl extends ServiceImpl<ISceneBuildProcessLogMapper, SceneBuildProcessLog> implements ISceneBuildProcessLogService {
+
+
+    @Override
+    public void clearSceneBuildProcessLog(String num, String process, String queueName) {
+        this.remove(new LambdaQueryWrapper<SceneBuildProcessLog>()
+                .eq(SceneBuildProcessLog::getNum, num)
+                .eq(SceneBuildProcessLog::getProcess, process)
+                .eq(SceneBuildProcessLog::getQueueName, queueName));
+    }
+
+    @Override
+    public void saveSceneBuildProcessLog(String num, String process, String queueName, int status, String reason) {
+
+        SceneBuildProcessLog log = this.getOne(new LambdaQueryWrapper<SceneBuildProcessLog>()
+                .eq(SceneBuildProcessLog::getNum, num)
+                .eq(SceneBuildProcessLog::getProcess,process)
+                .eq(SceneBuildProcessLog::getQueueName, queueName));
+        if(Objects.isNull(log)){
+            log = new SceneBuildProcessLog();
+        }
+        log.setNum(num);
+        log.setProcess(process);
+        log.setProcess(process);
+        log.setQueueName(queueName);
+        log.setState(status);
+        log.setReason(reason);
+        this.saveOrUpdate(log);
+    }
+}

+ 16 - 0
src/main/java/com/fdkankan/contro/service/impl/SceneFileBuildServiceImpl.java

@@ -28,6 +28,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
 import org.springframework.stereotype.Service;
 import org.springframework.util.ObjectUtils;
 
@@ -44,6 +45,7 @@ import java.util.*;
  * @author dengsixing
  * @since 2021-12-23
  */
+@RefreshScope
 @Slf4j
 @Service
 public class SceneFileBuildServiceImpl extends ServiceImpl<ISceneFileBuildMapper, SceneFileBuild> implements ISceneFileBuildService {
@@ -60,6 +62,10 @@ public class SceneFileBuildServiceImpl extends ServiceImpl<ISceneFileBuildMapper
     private String queueModelingPre;
 
 
+    @Value("${model.modelKind:3dtiles}")
+    private String modelKind;
+
+
     @Autowired
     private IScenePlusExtService scenePlusExtService;
 
@@ -228,6 +234,7 @@ public class SceneFileBuildServiceImpl extends ServiceImpl<ISceneFileBuildMapper
         if(cameraType.longValue() == 14 ){
             scenePlus.setSceneSource(4);
             scenePlusExt.setSceneScheme(10);
+            scenePlusExt.setModelKind(modelKind);
         }
 
         if (pic != null && pic.length() > 5) {
@@ -423,11 +430,19 @@ public class SceneFileBuildServiceImpl extends ServiceImpl<ISceneFileBuildMapper
         if(deleteExtras){
             message.getExt().put("deleteExtras",deleteExtras);
         }
+        if (force) {
+            message.setRebuild("1");
+        }
         rabbitMqProducer.sendByWorkQueue(queueModelingPre, message);
         scenePlusService.update(new LambdaUpdateWrapper<ScenePlus>()
             .set(ScenePlus::getSceneStatus, SceneStatus.wait.code())
             .eq(ScenePlus::getNum, num));
 
+        if(cameraType == 14){
+            scenePlusExt.setModelKind(this.modelKind);
+        }
+        scenePlusExtService.updateById(scenePlusExt);
+
         return ResultData.ok();
     }
 
@@ -483,6 +498,7 @@ public class SceneFileBuildServiceImpl extends ServiceImpl<ISceneFileBuildMapper
                     rebuild = 1;
                     sceneNum = scenePlus.getNum();
                 }
+
                 imgViewPath = String.format(UploadFilePath.IMG_VIEW_PATH, sceneNum);
                 if(fdageData.containsKey("icon") && StringUtils.isNotEmpty(fdageData.getString("icon"))){
                     String ossPath = ConstantFilePath.OSS_PREFIX + dataSource.replace(ConstantFilePath.BUILD_MODEL_PATH, "")

+ 5 - 0
src/main/resources/mapper/contro/SceneBuildProcessLogMapper.xml

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