Browse Source

Merge branch 'feature-v4.5.0-20221202' into release

dsx 2 years ago
parent
commit
5151b7a00a

+ 7 - 8
src/main/java/com/fdkankan/scene/bean/SceneJsonBean.java

@@ -3,14 +3,13 @@ package com.fdkankan.scene.bean;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.fdkankan.scene.vo.SceneEditControlsVO;
+import java.util.Date;
+import java.util.List;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
-import java.util.Date;
-import java.util.List;
-
 /**
  * <p>
  * scene.json实体类
@@ -92,11 +91,6 @@ public class SceneJsonBean {
      */
     private Integer linkVersion;
 
-//    /**
-//     * 户型图文件路径集合
-//     */
-//    private String[] floorPlanPaths;
-
     /**
      * 是否上传了户型图(0-否,1-是)
      */
@@ -123,6 +117,11 @@ public class SceneJsonBean {
     private String sceneKind;
 
     /**
+     * 算法模型类型(dam,3dtiles)
+     */
+    private String modelKind;
+
+    /**
      * 空间视频数据
      */
     private String boxVideos;

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

@@ -0,0 +1,21 @@
+package com.fdkankan.scene.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author 
+ * @since 2022-12-07
+ */
+@RestController
+@RequestMapping("/scene/sceneAsynOperLog")
+public class SceneAsynOperLogController {
+
+}
+

+ 22 - 1
src/main/java/com/fdkankan/scene/controller/SceneEditController.java

@@ -5,8 +5,10 @@ import com.fdkankan.common.constant.SceneInfoReqType;
 import com.fdkankan.common.exception.BusinessException;
 import com.fdkankan.model.utils.CreateHouseJsonUtil;
 import com.fdkankan.scene.annotation.CheckPermit;
+import com.fdkankan.scene.entity.SceneAsynOperLog;
 import com.fdkankan.scene.service.IBoxModelService;
 import com.fdkankan.scene.service.IDownloadTourVideoService;
+import com.fdkankan.scene.service.ISceneAsynOperLogService;
 import com.fdkankan.scene.service.ISceneEditInfoService;
 import com.fdkankan.scene.service.ISceneEditService;
 import com.fdkankan.scene.service.IScenePlusService;
@@ -31,9 +33,11 @@ import com.fdkankan.scene.vo.FileNameAndDataParamVO;
 import com.fdkankan.scene.vo.FileParamVO;
 import com.fdkankan.scene.vo.LocalesParamVO;
 import com.fdkankan.scene.vo.RenameCadParamVO;
+import com.fdkankan.scene.vo.SaveFiltersParamVO;
 import com.fdkankan.scene.vo.SaveLinkPanParamVO;
 import com.fdkankan.scene.vo.SaveTagsParamVO;
 import com.fdkankan.scene.vo.SaveTagsVisibleParamVO;
+import com.fdkankan.scene.vo.SceneAsynOperLogParamVO;
 import com.fdkankan.scene.vo.SceneAuthVO;
 import com.fdkankan.scene.vo.SceneEditInfoParamVO;
 import com.fdkankan.scene.vo.SceneEditInfoVO;
@@ -84,6 +88,8 @@ public class SceneEditController extends BaseController {
     private IBoxModelService boxModelService;
     @Autowired
     private IScenePlusService scenePlusService;
+    @Autowired
+    private ISceneAsynOperLogService sceneAsynOperLogService;
 
     /**
      * <p>
@@ -755,7 +761,7 @@ public class SceneEditController extends BaseController {
      */
     @CheckPermit
     @PostMapping(value = "/filter/save")
-    public ResultData saveFilter(@RequestBody @Validated BaseDataParamVO param) throws Exception{
+    public ResultData saveFilter(@RequestBody @Validated SaveFiltersParamVO param) throws Exception{
         return sceneEditInfoService.saveFilter(param);
     }
 
@@ -857,5 +863,20 @@ public class SceneEditController extends BaseController {
         return scenePlusService.uploadShareLogo(num, file);
     }
 
+    /**
+     * <p>
+     删除空间模型
+     * </p>
+     * @author dengsixing
+     * @date 2022/10/19
+     * @param param
+     * @return com.fdkankan.common.response.ResultData
+     **/
+    @CheckPermit
+    @PostMapping("/getAsynOperLog")
+    public ResultData getAsynOperLog(@RequestBody @Validated SceneAsynOperLogParamVO param){
+        return sceneAsynOperLogService.getAsynOperLog(param);
+    }
+
 
 }

+ 105 - 0
src/main/java/com/fdkankan/scene/entity/SceneAsynOperLog.java

@@ -0,0 +1,105 @@
+package com.fdkankan.scene.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author 
+ * @since 2022-12-07
+ */
+@Getter
+@Setter
+@TableName("t_scene_asyn_oper_log")
+public class SceneAsynOperLog implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 场景码
+     */
+    @TableField("num")
+    private String num;
+
+    /**
+     * 操作类型(upload-上传,download-下载)
+     */
+    @TableField("oper_type")
+    private String operType;
+
+    /**
+     * 模块名称
+     */
+    @TableField("module")
+    private String module;
+
+    /**
+     * 功能
+     */
+    @TableField("func")
+    private String func;
+
+    /**
+     * 版本号
+     */
+    @TableField("version")
+    private Integer version;
+
+    /**
+     * 状态(0-处理中,1-处理完成,2-处理失败)
+     */
+    @TableField("state")
+    private Integer state;
+
+    /**
+     * 下载链接
+     */
+    @TableField("url")
+    private String url;
+
+    /**
+     * 是否需要弹窗(0-否,1-是)
+     */
+    @TableField("pop")
+    private Integer pop;
+
+    /**
+     * 扩展信息
+     */
+    @TableField("ext_data")
+    private String extData;
+
+    /**
+     * 创建时间
+     */
+    @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/scene/entity/ScenePlusExt.java

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

+ 3 - 3
src/main/java/com/fdkankan/scene/generate/AutoGenerate.java

@@ -18,7 +18,7 @@ public class AutoGenerate {
         String path =System.getProperty("user.dir");
 
         generate(path,"scene", getTables(new String[]{
-                "t_scene_clean"
+                "t_scene_asyn_oper_log"
         }));
 
 //        generate(path,"goods", getTables(new String[]{
@@ -46,8 +46,8 @@ public class AutoGenerate {
 
 
     public static void  generate(String path,String moduleName,  List<String> tables){
-        FastAutoGenerator.create("jdbc:mysql://rm-wz90w10465iiwwv098o.mysql.rds.aliyuncs.com/4dkankan_v4",
-            "root","D2719bd0cae1a005")
+        FastAutoGenerator.create("jdbc:mysql://120.24.144.164:3306/4dkankan_v4",
+            "root","4Dage@4Dage#@168")
                 .globalConfig(builder -> {
                     builder.author("")               //作者
                             .outputDir(path+"\\src\\main\\java")    //输出路径(写到java目录)

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

@@ -0,0 +1,18 @@
+package com.fdkankan.scene.mapper;
+
+import com.fdkankan.scene.entity.SceneAsynOperLog;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2022-12-07
+ */
+@Mapper
+public interface ISceneAsynOperLogMapper extends BaseMapper<SceneAsynOperLog> {
+
+}

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

@@ -0,0 +1,27 @@
+package com.fdkankan.scene.schedule;
+
+import com.fdkankan.scene.service.ISceneAsynOperLogService;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+@RefreshScope
+@Log4j2
+@Component
+public class ScheduleJob {
+
+    @Autowired
+    private ISceneAsynOperLogService sceneAsynOperLogService;
+
+    /**
+     * 每天凌晨一点执行
+     */
+    @Scheduled(cron="0 0/5 * * * ?")
+    public void cleanDownloadPanorama() {
+        log.info("定时清除全景图压缩包开始");
+        sceneAsynOperLogService.cleanDownloadPanorama();
+        log.info("定时清除全景图压缩包完毕");
+    }
+}

+ 24 - 0
src/main/java/com/fdkankan/scene/service/ISceneAsynOperLogService.java

@@ -0,0 +1,24 @@
+package com.fdkankan.scene.service;
+
+import com.fdkankan.scene.entity.SceneAsynOperLog;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.scene.vo.SceneAsynOperLogParamVO;
+import com.fdkankan.web.response.ResultData;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestBody;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author 
+ * @since 2022-12-07
+ */
+public interface ISceneAsynOperLogService extends IService<SceneAsynOperLog> {
+
+    ResultData getAsynOperLog(SceneAsynOperLogParamVO param);
+
+    void cleanDownloadPanorama();
+
+}

+ 2 - 1
src/main/java/com/fdkankan/scene/service/ISceneEditInfoService.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fdkankan.scene.annotation.CheckPermit;
 import com.fdkankan.scene.vo.BaseSceneParamVO;
+import com.fdkankan.scene.vo.SaveFiltersParamVO;
 import com.fdkankan.scene.vo.SurveillanceParamVO;
 import com.fdkankan.web.response.ResultData;
 import com.fdkankan.scene.entity.SceneEditInfo;
@@ -109,7 +110,7 @@ public interface ISceneEditInfoService extends IService<SceneEditInfo> {
 
     ResultData deleteWaterMark(BaseFileParamVO param) throws Exception;
 
-    ResultData saveFilter(BaseDataParamVO param) throws Exception;
+    ResultData saveFilter(SaveFiltersParamVO param) throws Exception;
 
     ResultData listFilter(BaseSceneParamVO param) throws Exception;
 

+ 118 - 0
src/main/java/com/fdkankan/scene/service/impl/SceneAsynOperLogServiceImpl.java

@@ -0,0 +1,118 @@
+package com.fdkankan.scene.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.fdkankan.common.constant.CommonOperStatus;
+import com.fdkankan.common.constant.CommonStatus;
+import com.fdkankan.common.constant.SceneAsynFuncType;
+import com.fdkankan.common.constant.SceneAsynModuleType;
+import com.fdkankan.common.constant.SceneAsynOperType;
+import com.fdkankan.fyun.face.FYunFileServiceInterface;
+import com.fdkankan.scene.entity.SceneAsynOperLog;
+import com.fdkankan.scene.mapper.ISceneAsynOperLogMapper;
+import com.fdkankan.scene.service.ISceneAsynOperLogService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.scene.vo.SceneAsynOperLogParamVO;
+import com.fdkankan.web.response.ResultData;
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.List;
+import java.util.stream.Collectors;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author 
+ * @since 2022-12-07
+ */
+@Slf4j
+@Service
+public class SceneAsynOperLogServiceImpl extends ServiceImpl<ISceneAsynOperLogMapper, SceneAsynOperLog> implements ISceneAsynOperLogService {
+
+    @Autowired
+    private FYunFileServiceInterface fYunFileService;
+
+
+    @Override
+    public ResultData getAsynOperLog(SceneAsynOperLogParamVO param) {
+
+        LambdaQueryWrapper<SceneAsynOperLog> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(SceneAsynOperLog::getNum, param.getNum());
+        if(StrUtil.isNotEmpty(param.getOperType())){
+            queryWrapper.eq(SceneAsynOperLog::getOperType, param.getOperType());
+        }
+        if(StrUtil.isNotEmpty(param.getModule())){
+            queryWrapper.eq(SceneAsynOperLog::getModule, param.getModule());
+        }
+        if(StrUtil.isNotEmpty(param.getFunc())){
+            queryWrapper.eq(SceneAsynOperLog::getFunc, param.getFunc());
+        }
+
+        //需要弹窗的异步操作列表
+        List<SceneAsynOperLog> list = this.list(queryWrapper);
+
+        //如果列表中有需要弹窗并且处理完毕的,需要把这些数据改为不需要弹窗了,因为前端请求到之后就会弹出提示,下次不需要弹窗了
+        if(CollUtil.isNotEmpty(list)){
+            List<Long> idList = list.stream().filter(log -> {
+                if(!log.getState().equals(CommonOperStatus.WAITING.code())){
+                    return true;
+                }
+                return false;
+            }).map(log->log.getId()).collect(Collectors.toList());
+            if(CollUtil.isNotEmpty(idList)){
+                this.update(new LambdaUpdateWrapper<SceneAsynOperLog>()
+                    .set(SceneAsynOperLog::getPop, CommonStatus.NO.code())
+                    .in(SceneAsynOperLog::getId, idList));
+            }
+        }
+
+        return ResultData.ok(list);
+    }
+
+    @Override
+    public void cleanDownloadPanorama() {
+
+        List<SceneAsynOperLog> downloadList = this.list(
+            new LambdaQueryWrapper<SceneAsynOperLog>()
+                .eq(SceneAsynOperLog::getOperType, SceneAsynOperType.DOWNLOAD.code())
+                .eq(SceneAsynOperLog::getModule, SceneAsynModuleType.UPLOAD_DOWNLOAD.code())
+                .eq(SceneAsynOperLog::getFunc, SceneAsynFuncType.PANORAMIC_IMAGE.code()));
+        if(CollUtil.isEmpty(downloadList)){
+            return;
+        }
+        DateTime preMonth = DateUtil.offsetMonth(Calendar.getInstance().getTime(), -1);
+        List<SceneAsynOperLog> deleteList = downloadList.parallelStream().filter(log -> {
+            if (log.getCreateTime().before(preMonth)) {
+                return Boolean.TRUE;
+            }
+            return false;
+        }).collect(Collectors.toList());
+        if(CollUtil.isEmpty(deleteList)){
+            return;
+        }
+
+        //删除数据库记录
+        List<Long> deleteIdList = deleteList.parallelStream().map(item -> item.getId()).collect(Collectors.toList());
+        this.removeByIds(deleteIdList);
+
+        deleteList.parallelStream().forEach(item -> {
+            if(StrUtil.isNotEmpty(item.getUrl())){
+                try {
+                    fYunFileService.deleteFile(item.getUrl());
+                } catch (IOException e) {
+                    log.warn("删除oss全景图下载压缩包失败,key:{}", item.getUrl());
+                }
+            }
+        });
+
+    }
+}

+ 172 - 38
src/main/java/com/fdkankan/scene/service/impl/SceneEditInfoServiceImpl.java

@@ -1,4 +1,12 @@
 package com.fdkankan.scene.service.impl;
+import cn.hutool.core.util.CharsetUtil;
+import com.fdkankan.common.constant.CommonOperStatus;
+import com.fdkankan.common.constant.SceneAsynFuncType;
+import com.fdkankan.common.constant.SceneAsynModuleType;
+import com.fdkankan.common.constant.SceneAsynOperType;
+import com.fdkankan.scene.vo.SaveFiltersParamVO;
+import io.opencensus.metrics.LongGauge;
+import java.util.Date;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
@@ -44,6 +52,7 @@ import com.fdkankan.scene.bean.VertexBean;
 import com.fdkankan.scene.bean.WallBean;
 import com.fdkankan.scene.entity.CameraDetail;
 import com.fdkankan.scene.entity.Company;
+import com.fdkankan.scene.entity.SceneAsynOperLog;
 import com.fdkankan.scene.entity.SceneDataDownload;
 import com.fdkankan.scene.entity.SceneEditControls;
 import com.fdkankan.scene.entity.SceneEditInfo;
@@ -53,6 +62,7 @@ import com.fdkankan.scene.entity.ScenePlusExt;
 import com.fdkankan.scene.mapper.ISceneEditInfoMapper;
 import com.fdkankan.scene.service.ICameraDetailService;
 import com.fdkankan.scene.service.ICompanyService;
+import com.fdkankan.scene.service.ISceneAsynOperLogService;
 import com.fdkankan.scene.service.ISceneDataDownloadService;
 import com.fdkankan.scene.service.ISceneEditControlsService;
 import com.fdkankan.scene.service.ISceneEditInfoExtService;
@@ -103,6 +113,7 @@ import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Set;
 import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 import javax.annotation.Resource;
@@ -162,6 +173,8 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
     private ICompanyService companyService;
     @Autowired
     private ISurveillanceService surveillanceService;
+    @Autowired
+    private ISceneAsynOperLogService sceneAsynOperLogService;
 
     @Transactional
     @Override
@@ -272,6 +285,7 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         sceneJson.setSceneResolution(scenePlusExt.getSceneResolution());
         sceneJson.setSceneFrom(scenePlusExt.getSceneFrom());
         sceneJson.setSceneKind(scenePlusExt.getSceneKind());
+        sceneJson.setModelKind(scenePlusExt.getModelKind());
         if(StrUtil.isNotEmpty(scenePlusExt.getVideos())){
             sceneJson.setVideos(scenePlusExt.getVideos());
         }
@@ -458,6 +472,7 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         sceneInfoVO.setSceneResolution(scenePlusExt.getSceneResolution());
         sceneInfoVO.setSceneFrom(scenePlusExt.getSceneFrom());
         sceneInfoVO.setSceneKind(scenePlusExt.getSceneKind());
+        sceneInfoVO.setModelKind(scenePlusExt.getModelKind());
         sceneInfoVO.setVideos(scenePlusExt.getVideos());
         if(CommonStatus.YES.code().intValue() == sceneEditInfoExt.getMosaic()){
             sceneInfoVO.setMosaicList(this.getMosaicList(num));
@@ -715,6 +730,10 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         result.put("version", "2.1");
 
         String floorplanCadPath = String.format(UploadFilePath.DATA_VIEW_PATH, num) + "floorplan_cad.json";
+        if(!fYunFileService.fileExist(bucket, floorplanCadPath)){
+            log.warn("生成houseType.json失败,原因:floorplan_cad.json文件不存在,num:{}", num);
+            return;
+        }
         String floorcadStr = fYunFileService.getFileContent(bucket, floorplanCadPath);
 
         JSONObject floorcadObj = JSON.parseObject(floorcadStr);
@@ -929,6 +948,19 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         if(scenePlus == null){
             throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
         }
+
+        //查询是否存在等待中的异步操作记录,如果存在,抛出业务异常,终止操作
+        this.checkSceneAsynOper(num, null, SceneAsynModuleType.UPLOAD_DOWNLOAD.code() , SceneAsynFuncType.PANORAMIC_IMAGE.code());
+
+        //清除全景图异步操作记录,防止再次下载的时候请求到旧的压缩包
+        sceneAsynOperLogService.remove(
+            new LambdaQueryWrapper<SceneAsynOperLog>()
+            .eq(SceneAsynOperLog::getNum, num)
+            .eq(SceneAsynOperLog::getModule, SceneAsynModuleType.UPLOAD_DOWNLOAD.code())
+            .eq(SceneAsynOperLog::getFunc, SceneAsynFuncType.PANORAMIC_IMAGE.code())
+        );
+
+
         ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
         String bucket = scenePlusExt.getYunFileBucket();
 
@@ -954,9 +986,14 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         file.transferTo(targetFile);
 
         //如果是压缩包上传,需要解压缩
+        int async = CommonStatus.NO.code();
         if(file.getOriginalFilename().endsWith(".zip")){
+
+            //标记为异步处理
+            async = CommonStatus.YES.code();
+
             //解压zip包
-            ZipUtil.unzip(zipTargetFilePath,targetImagesPath);
+            ZipUtil.unzip(zipTargetFilePath,targetImagesPath, CharsetUtil.CHARSET_GBK);
             //删除压缩包
             FileUtils.delFile(zipTargetFilePath);
         }
@@ -1015,7 +1052,7 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
                     return filePath.substring(filePath.lastIndexOf(File.separator) + 1);
                 }).collect(Collectors.toList());
             }
-            return ResultData.ok(new UploadPanoramaVO(0, notExistFileList));
+            return ResultData.ok(new UploadPanoramaVO(0,0, notExistFileList));
         }
 
         //上传
@@ -1066,6 +1103,72 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
             CreateObjUtil.createSoftConnection(path + File.separator + "capture", target + File.separator + "capture");
         }
         fYunFileService.downloadFile(ConstantFilePath.OSS_PREFIX + path.replace(ConstantFilePath.BUILD_MODEL_PATH, "") + "/data.fdage", target + File.separator + "capture/data.fdage");
+
+        //如果部分成功,则需要返回成功数量和失败列表
+        if(CollUtil.isNotEmpty(notExistFileList)){
+            notExistFileList = notExistFileList.stream().map(filePath -> {
+                return filePath.substring(filePath.lastIndexOf(File.separator) + 1);
+            }).collect(Collectors.toList());
+        }
+
+        UploadPanoramaVO uploadPanoramaVO = new UploadPanoramaVO();
+        uploadPanoramaVO.setAsyn(async);
+        if(async == CommonStatus.YES.code().intValue()){
+            List<String> finalUploadFileList = uploadFileList;
+            List<String> finalNotExistFileList = notExistFileList;
+            CompletableFuture.runAsync(() -> {
+                SceneAsynOperLog sceneAsynOperLog = new SceneAsynOperLog();
+                sceneAsynOperLog.setNum(num);
+                sceneAsynOperLog.setOperType(SceneAsynOperType.UPLOAD.code());
+                sceneAsynOperLog.setModule(SceneAsynModuleType.UPLOAD_DOWNLOAD.code());
+                sceneAsynOperLog.setFunc(SceneAsynFuncType.PANORAMIC_IMAGE.code());
+                if(CollUtil.isNotEmpty(finalNotExistFileList)){
+                    Map<String, Object> extData = new HashMap<>();
+                    extData.put("successCnt", finalUploadFileList.size());
+                    extData.put("failList", finalNotExistFileList);
+                    sceneAsynOperLog.setExtData(JSON.toJSONString(extData));
+                }
+                sceneAsynOperLogService.save(sceneAsynOperLog);
+                try {
+                    this.uploadPanoramaHandler(num,bucket,target,imgViewPath, finalUploadFileList,targetImagesPath);
+                    sceneAsynOperLog.setState(CommonOperStatus.SUCCESS.code());
+                } catch (Exception e) {
+                    log.error("上传全景图报错,num:" + num, e);
+                    sceneAsynOperLog.setState(CommonOperStatus.FAILD.code());
+                }
+                sceneAsynOperLogService.updateById(sceneAsynOperLog);
+            });
+        }else{
+            this.uploadPanoramaHandler(num,bucket,target,imgViewPath,uploadFileList,targetImagesPath);
+            if(CollUtil.isNotEmpty(notExistFileList)){
+                uploadPanoramaVO.setSuccessCnt(uploadFileList.size());
+                uploadPanoramaVO.setFailList(notExistFileList);
+            }
+        }
+        return ResultData.ok(uploadPanoramaVO);
+    }
+
+    private void checkSceneAsynOper(String num, String operType, String module, String function){
+        LambdaQueryWrapper<SceneAsynOperLog> queryWrapper =
+            new LambdaQueryWrapper<SceneAsynOperLog>()
+                .eq(SceneAsynOperLog::getNum,num)
+                .eq(SceneAsynOperLog::getState, CommonOperStatus.WAITING.code());
+        if(StrUtil.isNotEmpty(operType)){
+            queryWrapper.eq(SceneAsynOperLog::getOperType, operType);
+        }
+        if(StrUtil.isNotEmpty(module)){
+            queryWrapper.eq(SceneAsynOperLog::getModule, module);
+        }
+        if(StrUtil.isNotEmpty(function)){
+            queryWrapper.eq(SceneAsynOperLog::getFunc, function);
+        }
+        List<SceneAsynOperLog> waittingLogList = sceneAsynOperLogService.list(queryWrapper);
+        if(CollUtil.isNotEmpty(waittingLogList)){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_5066);
+        }
+    }
+
+    public void uploadPanoramaHandler(String num, String bucket, String target, String imgViewPath, List<String> uploadFileList, String targetImagesPath) throws Exception {
         CreateObjUtil.build3dModel(target , "1");
 
         String uploadJsonPath= target + File.separator + "results" +File.separator+"upload.json";
@@ -1084,6 +1187,7 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         if(array == null){
             throw new BusinessException(ErrorCode.FAILURE_CODE_7013);
         }
+        Map<String, String> map = new HashMap<>();
         JSONObject fileJson = null;
         String fileName = "";
         for(int i = 0, len = array.size(); i < len; i++) {
@@ -1134,20 +1238,11 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         });
 
         //更新数据库版本号
+        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num);
         SceneEditInfo sceneEditInfo = this.getByScenePlusId(scenePlus.getId());
         this.upgradeVersionAndImgVersionById(sceneEditInfo.getId());
         //更新scenejson缓存和oss文件版本号
         this.upgradeSceneJsonVersion(num, sceneEditInfo.getVersion() + 1, sceneEditInfo.getImgVersion() + 1, bucket);
-
-        //如果部分成功,则需要返回成功数量和失败列表
-        if(CollUtil.isNotEmpty(notExistFileList)){
-            notExistFileList = notExistFileList.stream().map(filePath -> {
-                return filePath.substring(filePath.lastIndexOf(File.separator) + 1);
-            }).collect(Collectors.toList());
-            return ResultData.ok(new UploadPanoramaVO(uploadFileList.size(), notExistFileList));
-        }
-
-        return ResultData.ok();
     }
 
 
@@ -1162,6 +1257,10 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         if(Objects.isNull(scenePlus)){
             throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
         }
+
+        //查询是否存在等待中的异步操作记录,如果存在,抛出业务异常,终止操作
+        this.checkSceneAsynOper(num,null, SceneAsynModuleType.UPLOAD_DOWNLOAD.code() , SceneAsynFuncType.PANORAMIC_IMAGE.code());
+
         ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
         String bucket = scenePlusExt.getYunFileBucket();
         String path = scenePlusExt.getDataSource();
@@ -1176,8 +1275,9 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         //判断全景图缓存是否存在,如果不存在,从计算目录中拷贝到缓存目录
         this.cachePanorama(scenePlusExt.getDataSource(), num);
 
-        String url = null;
-        String downloadName = null;
+        Map<String, Object> map = new HashMap<>();
+
+        //标记是否是异步操作,默认是同步操作
         //如果入参文件名不为空,则是单个文件下载,不需要打包
         if(StrUtil.isNotEmpty(fileName)){
             //如果是单张图片,直接提供oss url
@@ -1187,36 +1287,65 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
                 throw new BusinessException(ErrorCode.FAILURE_CODE_5063);
             }
             fYunFileService.uploadFile(bucket, localFilePath, ossFilePath);
-            url = ossUrlPrefix + ossFilePath;
-            downloadName = fileName;
+            String url = ossUrlPrefix + ossFilePath;
+            String downloadName = fileName;
+            map.put("asyn", CommonStatus.NO.code());
+            map.put("fileUrl", url + "?t=" + System.currentTimeMillis());
+            map.put("fileName", downloadName);
+            return ResultData.ok(map);
         }else{
             if(!cn.hutool.core.io.FileUtil.exist(localImagesPath)
                 || cn.hutool.core.io.FileUtil.isDirEmpty(new File(localImagesPath))){
                 throw new BusinessException(ErrorCode.FAILURE_CODE_5063);
             }
 
-            downloadName = num + "_images.zip";
-            long start = Calendar.getInstance().getTimeInMillis();
-            //打包
-            String zipPath = cachePath + downloadName;
-            ZipUtil.zip(localImagesPath, zipPath);
-            long end1 = Calendar.getInstance().getTimeInMillis();
-            log.info("打包耗时:" + (end1 - start));
-            //上传压缩包
-            fYunFileService.uploadFileByCommand(bucket, zipPath, String.format(cacheFormat, num) + downloadName);
-            url = ossUrlPrefix + String.format(cacheFormat, num) + downloadName;
-            long end2 = Calendar.getInstance().getTimeInMillis();
-            log.info("上传耗时:" + (end2 - end1));
-            //删除本地压缩包
-            FileUtils.deleteFile(zipPath);
-//            //删除本地目录
-            FileUtils.deleteDirectory(localImagesPath);
-        }
+            //清除旧的下载记录
+            sceneAsynOperLogService.remove(
+                new LambdaQueryWrapper<SceneAsynOperLog>()
+                    .eq(SceneAsynOperLog::getNum, num)
+                    .eq(SceneAsynOperLog::getOperType, SceneAsynOperType.DOWNLOAD.code())
+                    .eq(SceneAsynOperLog::getModule, SceneAsynModuleType.UPLOAD_DOWNLOAD.code())
+                    .eq(SceneAsynOperLog::getFunc, SceneAsynFuncType.PANORAMIC_IMAGE.code()));
+
+            //开始异步执行下载全景图压缩包操作
+            CompletableFuture.runAsync(() -> {
+                SceneEditInfo sceneEditInfo = this.getByScenePlusId(scenePlus.getId());
+                SceneAsynOperLog sceneAsynOperLog = new SceneAsynOperLog();
+                sceneAsynOperLog.setNum(num);
+                sceneAsynOperLog.setOperType(SceneAsynOperType.DOWNLOAD.code());
+                sceneAsynOperLog.setModule(SceneAsynModuleType.UPLOAD_DOWNLOAD.code());
+                sceneAsynOperLog.setFunc(SceneAsynFuncType.PANORAMIC_IMAGE.code());
+                sceneAsynOperLog.setVersion(sceneEditInfo.getImgVersion());
+                sceneAsynOperLogService.save(sceneAsynOperLog);
+                try {
+                    String downloadName = num + "_images.zip";
+                    long start = Calendar.getInstance().getTimeInMillis();
+                    //打包
+                    String zipPath = cachePath + downloadName;
+                    ZipUtil.zip(localImagesPath, zipPath);
+                    long end1 = Calendar.getInstance().getTimeInMillis();
+                    log.info("打包耗时:" + (end1 - start));
+                    //上传压缩包
+                    fYunFileService.uploadFileByCommand(bucket, zipPath, String.format(cacheFormat, num) + downloadName);
+                    String url = String.format(cacheFormat, num) + downloadName;
+                    long end2 = Calendar.getInstance().getTimeInMillis();
+                    log.info("上传耗时:" + (end2 - end1));
+                    //删除本地压缩包
+                    FileUtils.deleteFile(zipPath);
+                    //删除本地目录
+                    FileUtils.deleteDirectory(localImagesPath);
+                    sceneAsynOperLog.setState(CommonOperStatus.SUCCESS.code());
+                    sceneAsynOperLog.setUrl(url);
+                }catch (Exception e){
+                    sceneAsynOperLog.setState(CommonOperStatus.FAILD.code());
+                    log.error("下载全景图压缩包失败,num:" + num, e);
+                }
+                sceneAsynOperLogService.saveOrUpdate(sceneAsynOperLog);
+            });
 
-        Map<String, Object> map = new HashMap<>();
-        map.put("fileUrl", url + "?t=" + System.currentTimeMillis());
-        map.put("fileName", downloadName);
-        return ResultData.ok(map);
+            map.put("asyn", CommonStatus.YES.code());
+            return ResultData.ok(map);
+        }
     }
 
     private void cachePanorama(String dataSource, String num){
@@ -2601,7 +2730,7 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
     }
 
     @Override
-    public ResultData saveFilter(BaseDataParamVO param) throws Exception {
+    public ResultData saveFilter(SaveFiltersParamVO param) throws Exception {
 
         ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
         if(Objects.isNull(scenePlus)){
@@ -2622,6 +2751,11 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         //写本地文件,作为备份
         this.writeFilter(param.getNum());
 
+        //如果页面选择恢复默认,filters字段值为否
+        if(Objects.nonNull(param.getReset()) && param.getReset() == CommonStatus.YES.code().intValue()){
+            filters = CommonStatus.NO.code();
+        }
+
         //更新数据库
         SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByScenePlusId(scenePlus.getId());
         sceneEditInfoExt.setFilters(filters);

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

@@ -222,8 +222,8 @@ public class ScenePlusServiceImpl extends ServiceImpl<IScenePlusMapper, ScenePlu
         String outPathEn = ConstantFilePath.BASE_PATH + File.separator + "sceneQRcode/"+num+"_en.png";
 
         String webSize = mainUrl + "/" + sceneProNewUrl + num;
-        QrCodeUtil.generate(webSize, QrConfig.create().setImg(logoPath), FileUtil.file(outPathZh));
-        QrCodeUtil.generate(webSize + "&lang=en", QrConfig.create().setImg(logoPath), FileUtil.file(outPathEn));
+        QrCodeUtil.generate(webSize, QrConfig.create().setImg(logoPath).setWidth(512).setHeight(512), FileUtil.file(outPathZh));
+        QrCodeUtil.generate(webSize + "&lang=en", QrConfig.create().setImg(logoPath).setWidth(512).setHeight(512), FileUtil.file(outPathEn));
         //上传logo图片
         String ossLogoPath = String.format(UploadFilePath.DOWNLOADS_QRCODE, num) + "shareLogo" + extName;
         fYunFileService.uploadFile(scenePlusExt.getYunFileBucket(), logoPath, ossLogoPath);

+ 186 - 35
src/main/java/com/fdkankan/scene/service/impl/SceneProServiceImpl.java

@@ -2,6 +2,7 @@ package com.fdkankan.scene.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.RuntimeUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.ZipUtil;
 import com.alibaba.fastjson.JSON;
@@ -10,12 +11,9 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.fdkankan.common.constant.CommonStatus;
+import com.fdkankan.common.constant.*;
 import com.fdkankan.model.constants.ConstantFileName;
 import com.fdkankan.model.constants.ConstantFilePath;
-import com.fdkankan.common.constant.ErrorCode;
-import com.fdkankan.common.constant.FileBizType;
-import com.fdkankan.common.constant.ServerCode;
 import com.fdkankan.model.constants.UploadFilePath;
 import com.fdkankan.common.exception.BusinessException;
 import com.fdkankan.web.response.ResultData;
@@ -56,6 +54,7 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import java.io.File;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Comparator;
@@ -213,11 +212,15 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
         if (scenePlus == null)
             throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
         ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
+        String bucket = scenePlusExt.getYunFileBucket();
 
         List<String> deleteSidList = param.getSidList();
 
         //处理删除状态数据
-        this.deleteHotData(param.getNum(), deleteSidList, scenePlusExt.getYunFileBucket());
+        this.deleteHotData(param.getNum(), deleteSidList, bucket);
+
+        //删除导览中的热点数据
+        this.deleteHotDataFromTourJson(param.getNum(), param.getSidList(), bucket);
 
         //写入本地文件,作为备份
         this.writeHotJson(param.getNum());
@@ -230,6 +233,31 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
         return ResultData.ok();
     }
 
+    private void deleteHotDataFromTourJson(String num, List<String> sidList, String bucket){
+        String key = String.format(UploadFilePath.USER_EDIT_PATH, num) + "tour.json";
+        String tourJson = fYunFileService.getFileContent(bucket, key);
+        if(StrUtil.isEmpty(tourJson)){
+            return;
+        }
+        JSONArray jsonArray = JSON.parseArray(tourJson);
+        if(CollUtil.isEmpty(jsonArray)){
+            return;
+        }
+        jsonArray.stream().forEach(tour->{
+            JSONObject obj = (JSONObject) tour;
+            JSONArray itemArra = obj.getJSONArray("list");
+            itemArra.stream().forEach(item->{
+                JSONObject itemObj = (JSONObject) item;
+                String tagId = itemObj.getString("tagId");
+                if(tagId != null && sidList.contains(tagId)){
+                    itemObj.remove("tagId");
+                }
+            });
+        });
+        fYunFileService.uploadFile(bucket, jsonArray.toJSONString().getBytes(StandardCharsets.UTF_8), key);
+
+    }
+
     @Override
     public ResultData deleteIcons(DeleteHotIconParamVO param) throws Exception {
 
@@ -677,29 +705,12 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
         ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
         String bucket = scenePlusExt.getYunFileBucket();
 
-        //文件上传的位置可以自定义
-        String path = scenePlusExt.getDataSource() + "_obj2txt";
-        String zipPath = path + "/zip/";
-        String filePath =  path + "/extras/";
-        String resultPath = path + "/results/";
-
-        //压缩文件处理:解压缩,解压缩后复制等操作
-        this.objAndImgFileHandler(resultPath, filePath, zipPath, file);
-
-        //创建data.json
-        this.writeDataJson(path);
-
-        //调用算法,不同的类型调用不同的算法
-        if("V2".equals(scenePlusExt.getBuildType())){
-            CreateObjUtil.objToTxt(path , "1");
-        }
-        if("V3".equals(scenePlusExt.getBuildType())){
-            CreateObjUtil.build3dModel(path , "1");
+        if(ModelKind.THREE_D_TILE.code().equals(scenePlusExt.getModelKind())){
+            this.buildModel43dtiles(num, bucket, scenePlusExt.getDataSource(), file);
+        }else{
+            this.buildModel4Dam(num, bucket, scenePlusExt.getDataSource(), scenePlusExt.getBuildType(), file);
         }
 
-        //算法计算完后,生成压缩文件,上传到oss
-        this.uploadFileofterRebuildPanoram(path, num, bucket);
-
         //更新版本信息
         SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
         if(Objects.isNull(sceneEditInfo)){
@@ -724,6 +735,111 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
         return ResultData.ok();
     }
 
+    /**
+     * 老算法(dam)上传模型逻辑
+     * @param num
+     * @param bucket
+     * @param dataSource
+     * @param buildType
+     * @throws Exception
+     */
+    private void buildModel4Dam(String num, String bucket, String dataSource, String buildType, MultipartFile file) throws Exception {
+        //文件上传的位置可以自定义
+        String path = dataSource + "_obj2txt";
+        String zipPath = path + "/zip/";
+        String filePath =  path + "/extras/";
+        String resultPath = path + "/results/";
+
+        //压缩文件处理:解压缩,解压缩后复制等操作
+        this.objAndImgFileHandler(resultPath, filePath, zipPath, file);
+
+        //创建data.json
+        this.writeDataJson(path);
+
+        //调用算法,不同的类型调用不同的算法
+        if("V2".equals(buildType)){
+            CreateObjUtil.objToTxt(path , "1");
+        }
+        if("V3".equals(buildType)){
+            CreateObjUtil.build3dModel(path , "1");
+        }
+
+        //算法计算完后,生成压缩文件,上传到oss
+        this.uploadFileofterRebuildPanoram(path, num, bucket);
+    }
+
+    /**
+     * 新算法(3dtiles)上传模型逻辑
+     * @param num
+     * @param bucket
+     * @param dataSource
+     * @throws Exception
+     */
+    private void buildModel43dtiles(String num, String bucket, String dataSource, MultipartFile file) throws Exception {
+        //文件上传的位置可以自定义
+        String path = dataSource + "_obj2Tiles" + File.separator;
+        String meshPath = path  + "mesh";
+        String zipPath = path + "zip" + File.separator;
+        String zipFilePath = zipPath + file.getOriginalFilename();
+
+
+        //压缩文件处理:解压缩,解压缩后复制等操作
+        FileUtil.del(path);
+        FileUtil.mkdir(zipPath);
+        File zipFile = new File(zipFilePath);
+        file.transferTo(zipFile);
+        ZipUtil.unzip(zipFilePath, meshPath);
+
+        //检测文件
+        String floorsJsonPath = meshPath + File.separator + "floors.json";
+        if(!FileUtil.exist(floorsJsonPath)){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_5068);
+        }
+        String floorsJsonStr = FileUtil.readUtf8String(floorsJsonPath);
+        JSONObject floorsJsonObj = JSON.parseObject(floorsJsonStr);
+        JSONArray floorArr = floorsJsonObj.getJSONArray("floors");
+        if(CollUtil.isEmpty(floorArr)){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_5069);
+        }
+        floorArr.stream().forEach(item->{
+            JSONObject itemObj = (JSONObject) item;
+            //楼层目录是否存在
+            String name = itemObj.getString("name");
+            if(StrUtil.isEmpty(name) || !FileUtil.exist(meshPath + File.separator + name)){
+                throw new BusinessException(ErrorCode.FAILURE_CODE_5070);
+            }
+            //检测obj文件是否存在
+            String objPath = itemObj.getString("objPath");
+            if(StrUtil.isEmpty(objPath) || !FileUtil.exist(path + objPath)){
+                throw new BusinessException(ErrorCode.FAILURE_CODE_5070);
+            }
+        });
+
+        //调用算法
+        String command = "bash //home/ubuntu/bin/Obj2Tiles.sh " + path;
+        log.info("上传3dtiles模型开始, num:{}, targetPath:{}", num, path);
+        RuntimeUtil.exec(command);
+        log.info("上传3dtiles模型结束, num:{}, targetPath:{}", num, path);
+
+        //检测计算结果
+        String tilesPath = path + "3dtiles";
+        String tilesetJsonPath = tilesPath + File.separator + "tileset.json";
+        boolean success = ComputerUtil.checkComputeCompleted(tilesetJsonPath, maxCheckTimes, waitTime);
+        if(!success){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_7013);
+        }
+
+        //删除logs
+        FileUtil.del(tilesPath + File.separator + "logs");
+
+        //算法计算完后,生成压缩文件,上传到oss
+        //上传3dtiles
+        fYunFileService.uploadFileByCommand(bucket, tilesPath, String.format(UploadFilePath.IMG_VIEW_PATH, num) + "3dtiles");
+        //上传mesh
+        fYunFileService.uploadFileByCommand(bucket, meshPath, String.format(UploadFilePath.DATA_VIEW_PATH, num) + "mesh");
+
+    }
+
     private void uploadFileofterRebuildPanoram(String path, String sceneNum, String bucket) throws Exception {
         //因为共享目录有延迟,这里循环检测算法是否计算完毕3次,每次隔五秒
         String uploadJsonPath = path + File.separator + "results" +File.separator+"upload.json";
@@ -889,6 +1005,46 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
 
         SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
 
+        if(ModelKind.THREE_D_TILE.code().equals(scenePlusExt.getModelKind())){
+            return this.downloadModel43dtiles(num, bucket, scenePlusExt, sceneEditInfo);
+        }
+
+        return this.downloadModel4Dam(num, bucket, scenePlusExt, sceneEditInfo);
+    }
+
+    @Override
+    public ScenePro getByNum(String num) {
+        return this.getOne(new LambdaQueryWrapper<ScenePro>().eq(ScenePro::getNum, num));
+    }
+
+    private ResultData downloadModel43dtiles(String num, String bucket, ScenePlusExt scenePlusExt, SceneEditInfo sceneEditInfo){
+
+        //下载mesh到本地
+        String meshOssPath = String.format(UploadFilePath.DATA_VIEW_PATH, num) + "mesh/";
+        String meshLocalPath = String.format(ConstantFilePath.SCENE_DATA_PATH_V4, num) + "mesh";
+        String zipName = num + "_mesh.zip";
+        String zipFilePath = String.format(ConstantFilePath.SCENE_DATA_PATH_V4, num) + zipName;
+        //下载
+        fYunFileService.downloadFileByCommand(bucket, meshLocalPath, meshOssPath);
+        //打包
+        ZipUtil.zip(meshLocalPath,zipFilePath);
+        //上传压缩包
+        fYunFileService.uploadFile(bucket, zipFilePath, "downloads/extras/" + zipName);
+        //删除本地文件
+        FileUtil.del(meshLocalPath);
+        FileUtil.del(zipFilePath);
+        String url = ossUrlPrefix + "downloads/extras/" + zipName + "?t=" + Calendar.getInstance().getTimeInMillis();
+        return ResultData.ok(url);
+    }
+
+    public static void main(String[] args) {
+
+        ZipUtil.zip("C:\\Users\\dsx\\Desktop\\新建文件夹\\temp\\mesh\\aaa\\mesh", "C:\\Users\\dsx\\Desktop\\新建文件夹\\temp\\mesh\\aaa\\mesh\\mesh.zip");
+        System.out.println(123);
+    }
+
+
+    private ResultData downloadModel4Dam(String num, String bucket, ScenePlusExt scenePlusExt, SceneEditInfo sceneEditInfo){
         String localImagePath = String.format(ConstantFilePath.IMAGESBUFFER_FORMAT, num);
         if(!new File(localImagePath).exists()){
             new File(localImagePath).mkdirs();
@@ -901,8 +1057,8 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
         String zipPath = localImagePath + zipName;
         //如果用户上传过模型,就打包上传到oss,直接返回
         if(CommonStatus.YES.code().equals(sceneEditInfo.getIsUploadObj())
-            && new File(newData).exists()
-            && new File(newResultData).exists()){
+                && new File(newData).exists()
+                && new File(newResultData).exists()){
             //打包
             ZipUtil.zip(newData, zipPath);
             //上传压缩包
@@ -929,11 +1085,11 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
                     if(file.isDirectory()){
                         for (File item : file.listFiles()) {
                             if(item.getName().endsWith(".obj") && !"output.house.obj".equals(item.getName()) &&
-                                !"mesh.obj".equals(item.getName())){
+                                    !"mesh.obj".equals(item.getName())){
                                 item.delete();
                             }
                             if(item.getName().endsWith(".mtl") && !"output.house.mtl".equals(item.getName()) &&
-                                !"mesh.mtl".equals(item.getName())){
+                                    !"mesh.mtl".equals(item.getName())){
                                 item.delete();
                             }
                         }
@@ -1004,9 +1160,4 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
         String url = ossUrlPrefix + "downloads/extras/" + zipName + "?t=" + Calendar.getInstance().getTimeInMillis();
         return ResultData.ok(url);
     }
-
-    @Override
-    public ScenePro getByNum(String num) {
-        return this.getOne(new LambdaQueryWrapper<ScenePro>().eq(ScenePro::getNum, num));
-    }
 }

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

@@ -0,0 +1,20 @@
+package com.fdkankan.scene.vo;
+
+import javax.validation.constraints.NotBlank;
+import lombok.Data;
+
+/**
+ * <p>
+ * 通用data类型参数类
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/2/10
+ **/
+@Data
+public class SaveFiltersParamVO extends BaseDataParamVO{
+
+    //是否恢复默认(0-否,1-是)
+    private Integer reset;
+
+}

+ 35 - 0
src/main/java/com/fdkankan/scene/vo/SceneAsynOperLogParamVO.java

@@ -0,0 +1,35 @@
+package com.fdkankan.scene.vo;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * <p>
+ * TODO
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/12/7
+ **/
+@Data
+public class SceneAsynOperLogParamVO extends BaseSceneParamVO{
+
+    /**
+    * 操作类型(upload-上传,download-下载)
+    */
+    private String operType;
+
+    /**
+     * 模块名称
+     */
+    private String module;
+
+    /**
+     * 功能
+     */
+    private String func;
+
+
+}

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

@@ -2,6 +2,7 @@ package com.fdkankan.scene.vo;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.annotation.TableField;
 import java.util.List;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
@@ -135,6 +136,11 @@ public class SceneInfoVO {
     private String sceneKind;
 
     /**
+     * 算法模型类型(dam,3dtiles)
+     */
+    private String modelKind;
+
+    /**
      * 空间视频数据
      */
     private String boxVideos;

+ 2 - 0
src/main/java/com/fdkankan/scene/vo/UploadPanoramaVO.java

@@ -20,6 +20,8 @@ import lombok.NoArgsConstructor;
 @AllArgsConstructor
 public class UploadPanoramaVO {
 
+    private int asyn;
+
     private Integer successCnt;
 
     private List<String> failList;

+ 5 - 0
src/main/resources/mapper/scene/SceneAsynOperLogMapper.xml

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