Просмотр исходного кода

Merge branch 'test' into project-qczj-20220713

# Conflicts:
#	4dkankan-center-scene-download/src/main/java/com/fdkankan/download/service/impl/SceneDownloadHandlerServiceImpl.java
#	4dkankan-center-scene/src/main/java/com/fdkankan/scene/listener/RabbitMqListener.java
#	4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/ISceneEditInfoService.java
#	4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/BuildScenePostServiceImpl.java
#	4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/SceneEditInfoServiceImpl.java
#	4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/SceneServiceImpl.java
dengsixing 3 лет назад
Родитель
Сommit
9526426d54
16 измененных файлов с 573 добавлено и 203 удалено
  1. 25 27
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/bean/SceneJsonBean.java
  2. 51 1
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/controller/SceneEditController.java
  3. 1 1
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/controller/V3Controller.java
  4. 12 0
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/entity/SceneEditInfo.java
  5. 9 3
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/entity/SceneEditInfoExt.java
  6. 2 0
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/entity/SceneProV3.java
  7. 14 3
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/ISceneEditInfoService.java
  8. 1 1
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/ISceneService.java
  9. 329 152
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/SceneEditInfoServiceImpl.java
  10. 2 1
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/SceneEditServiceImpl.java
  11. 4 2
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/SceneProServiceImpl.java
  12. 65 10
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/SceneServiceImpl.java
  13. 5 0
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/SceneUploadServiceImpl.java
  14. 1 0
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/vo/BaseDataParamVO.java
  15. 28 0
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/vo/DeleteMosaicParamVO.java
  16. 24 2
      4dkankan-center-scene/src/main/java/com/fdkankan/scene/vo/SceneInfoVO.java

+ 25 - 27
4dkankan-center-scene/src/main/java/com/fdkankan/scene/bean/SceneJsonBean.java

@@ -77,21 +77,21 @@ public class SceneJsonBean {
      */
     private Date createTime;
 
-//    /**
-//     * 点位数量
-//     */
-//    private Integer panoCount;
-//
-//    /**
-//     * 球幕视频数量
-//     */
-//    private Integer videoCount;
-
     /**
      * 版本
      */
     private Integer version;
 
+    /**
+     * 图片版本
+     */
+    private Integer imgVersion;
+
+    /**
+     * 场景关联版本
+     */
+    private Integer linkVersion;
+
 //    /**
 //     * 户型图文件路径集合
 //     */
@@ -102,23 +102,6 @@ public class SceneJsonBean {
      */
     private Byte floorPlanUser;
 
-//    private String cadInfo;
-
-//    /**
-//     * 是否上传模型
-//     */
-//    private Byte isUploadObj;
-//
-//    /**
-//     * 重新建模的版本
-//     */
-//    private Integer floorEditVer;
-//
-//    /**
-//     * 正式发布重新建模的版本
-//     */
-//    private Integer floorPublishVer;
-
     /**
      * 初始点信息
      */
@@ -191,5 +174,20 @@ public class SceneJsonBean {
      */
     private Integer links;
 
+    /**
+     * 是否有马赛克
+     */
+    private Integer mosaic;
+
+    /**
+     * 马赛克列表
+     */
+    private List<JSONObject> mosaicList;
+
+    /**
+     * 水印文件名
+     */
+    private String waterMark;
+
 
 }

+ 51 - 1
4dkankan-center-scene/src/main/java/com/fdkankan/scene/controller/SceneEditController.java

@@ -725,7 +725,7 @@ public class SceneEditController extends BaseController {
      **/
     @CheckCooperationPermit
     @PostMapping(value = "/cad/reset")
-    public ResultData resetCad(@RequestParam(value = "num") String num){
+    public ResultData resetCad(@RequestParam(value = "num") String num) throws Exception {
         return sceneEditInfoService.resetCad(num);
     }
 
@@ -1007,6 +1007,56 @@ public class SceneEditController extends BaseController {
         return sceneEditInfoService.addMosaics(param);
     }
 
+    /**
+     * 删除马赛克
+     * @param param
+     * @return
+     * @throws Exception
+     */
+    @CheckCooperationPermit
+    @PostMapping(value = "/mosaics/delete")
+    public ResultData deleteMosaics(@RequestBody @Validated DeleteMosaicParamVO param) throws Exception{
+        return sceneEditInfoService.deleteMosaics(param);
+    }
+
+    /**
+     * 删除马赛克
+     * @param param
+     * @return
+     * @throws Exception
+     */
+    @CheckCooperationPermit
+    @PostMapping(value = "/mosaics/list")
+    public ResultData getMosaicList(@RequestBody @Validated BaseSceneParamVO param) throws Exception{
+        return ResultData.ok(sceneEditInfoService.getMosaicList(param.getNum()));
+    }
+
+    /**
+     * 保存水印
+     * @param param
+     * @return
+     * @throws Exception
+     */
+    @CheckCooperationPermit
+    @PostMapping(value = "/waterMark/add")
+    public ResultData addWaterMark(@RequestBody @Validated BaseFileParamVO param) throws Exception{
+        return sceneEditInfoService.addWaterMark(param);
+    }
+
+    /**
+     * 删除水印
+     * @param param
+     * @return
+     * @throws Exception
+     */
+    @CheckCooperationPermit
+    @PostMapping(value = "/waterMark/delete")
+    public ResultData deleteWaterMark(@RequestBody @Validated BaseFileParamVO param) throws Exception{
+        return sceneEditInfoService.deleteWaterMark(param);
+    }
+
+
+
 
 
 

+ 1 - 1
4dkankan-center-scene/src/main/java/com/fdkankan/scene/controller/V3Controller.java

@@ -119,7 +119,7 @@ public class V3Controller extends BaseController {
      **/
     @PostMapping(value = "/copyScene")
     public ResultData copyScene(
-            @RequestBody @Validated CopySceneParamVO param) throws IOException {
+            @RequestBody @Validated CopySceneParamVO param) throws Exception {
         sceneService.copyScene(param);
         return ResultData.ok();
     }

+ 12 - 0
4dkankan-center-scene/src/main/java/com/fdkankan/scene/entity/SceneEditInfo.java

@@ -107,6 +107,18 @@ public class SceneEditInfo implements Serializable {
     private Integer version;
 
     /**
+     * 图片版本
+     */
+    @TableField("img_version")
+    private Integer imgVersion;
+
+    /**
+     * 场景关联版本
+     */
+    @TableField("link_version")
+    private Integer linkVersion;
+
+    /**
      * 是否上传模型
      */
     @TableField("is_upload_obj")

+ 9 - 3
4dkankan-center-scene/src/main/java/com/fdkankan/scene/entity/SceneEditInfoExt.java

@@ -56,10 +56,16 @@ public class SceneEditInfoExt {
     private Integer tours;
 
     /**
-     * mosaics数据
+     * 是否有马赛克
      */
-    @TableField("mosaics")
-    private String mosaics;
+    @TableField("mosaic")
+    private Integer mosaic;
+
+    /**
+     * 水印文件名
+     */
+    @TableField("water_mark")
+    private String waterMark;
 
     /**
      * 是否有场景关联(0-否,1-是)

+ 2 - 0
4dkankan-center-scene/src/main/java/com/fdkankan/scene/entity/SceneProV3.java

@@ -224,5 +224,7 @@ public class SceneProV3 implements Serializable {
     @TableLogic
     private Integer tbStatus;
 
+    private Integer isUpgrade;
+
 
 }

+ 14 - 3
4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/ISceneEditInfoService.java

@@ -1,6 +1,7 @@
 package com.fdkankan.scene.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.alibaba.fastjson.JSONObject;
 import com.fdkankan.common.response.ResultData;
 import com.fdkankan.scene.entity.SceneEditInfo;
 import com.fdkankan.scene.vo.BallScreenVideoParamVO;
@@ -20,6 +21,7 @@ import com.fdkankan.scene.vo.SceneEditInfoVO;
 import com.fdkankan.scene.vo.SceneInfoParamVO;
 import com.fdkankan.scene.vo.SceneInfoVO;
 import java.io.IOException;
+import java.util.List;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.multipart.MultipartFile;
@@ -48,13 +50,15 @@ public interface ISceneEditInfoService extends IService<SceneEditInfo> {
 
     ResultData saveCad(BaseDataParamVO param) throws Exception;
 
-    ResultData resetCad(String num);
+    ResultData resetCad(String num) throws IOException;
 
     ResultData renameCad(RenameCadParamVO param) throws IOException;
 
     void upgradeVersionById(Long id);
 
-    void upgradeSceneJsonVersion(String num, int version) throws IOException ;
+    void upgradeVersionAndImgVersionById(Long id);
+
+    void upgradeSceneJsonVersion(String num, int version, Integer imgVersion) throws IOException ;
 
     ResultData uploadPanorama(String num, MultipartFile file) throws Exception;
 
@@ -80,7 +84,7 @@ public interface ISceneEditInfoService extends IService<SceneEditInfo> {
 
     ResultData checkKey(SceneCheckKeyParamVO param) throws Exception;
 
-    ResultData addMosaics(@RequestBody @Validated BaseDataParamVO param) throws Exception;
+    ResultData addMosaics(BaseDataParamVO param) throws Exception;
 
     ResultData uploadLinkPan(String num, String sid, String fileName, MultipartFile file) throws Exception;
 
@@ -92,6 +96,13 @@ public interface ISceneEditInfoService extends IService<SceneEditInfo> {
 
     ResultData deleteStyles(DeleteLinkSceneStylesParamVO param) throws Exception;
 
+    ResultData deleteMosaics(DeleteMosaicParamVO param) throws Exception;
+
+    List<JSONObject> getMosaicList(String num) throws Exception;
+
+    ResultData addWaterMark(BaseFileParamVO param) throws Exception;
+
+    ResultData deleteWaterMark(BaseFileParamVO param) throws Exception;
 
 
 

+ 1 - 1
4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/ISceneService.java

@@ -100,5 +100,5 @@ public interface ISceneService extends IService<Scene> {
 
     Long getSceneCount(Long cameraId, Long userId);
 
-    void copyScene(CopySceneParamVO copySceneParamVO) throws IOException;
+    void copyScene(CopySceneParamVO copySceneParamVO) throws Exception;
 }

+ 329 - 152
4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/SceneEditInfoServiceImpl.java

@@ -17,6 +17,7 @@ import com.fdkankan.common.exception.BusinessException;
 import com.fdkankan.common.response.Result;
 import com.fdkankan.common.response.ResultData;
 import com.fdkankan.common.util.ComputerUtil;
+import com.fdkankan.common.util.CreateHouseJsonUtil;
 import com.fdkankan.common.util.CreateObjUtil;
 import com.fdkankan.common.util.FileMd5Util;
 import com.fdkankan.common.util.FileUtil;
@@ -29,10 +30,15 @@ import com.fdkankan.redis.constant.RedisLockKey;
 import com.fdkankan.redis.util.RedisLockUtil;
 import com.fdkankan.redis.util.RedisUtil;
 import com.fdkankan.scene.bean.BoxPhotoBean;
+import com.fdkankan.scene.bean.IconBean;
+import com.fdkankan.scene.bean.PointBean;
 import com.fdkankan.scene.bean.RequestSceneProV4;
 import com.fdkankan.scene.bean.SceneJsonBean;
+import com.fdkankan.scene.bean.SegmentBean;
 import com.fdkankan.scene.bean.StyleBean;
 import com.fdkankan.scene.bean.TagBean;
+import com.fdkankan.scene.bean.VertexBean;
+import com.fdkankan.scene.bean.WallBean;
 import com.fdkankan.scene.callback.FdkkMiniReqErrorCallback;
 import com.fdkankan.scene.callback.FdkkMiniReqSuccessCallback;
 import com.fdkankan.scene.entity.SceneDataDownload;
@@ -64,6 +70,7 @@ import java.io.File;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.HashMap;
@@ -75,6 +82,7 @@ import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
+import javax.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -144,7 +152,7 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
     IScenePlusService scenePlusService;
     @Autowired
     IScenePlusExtService scenePlusExtService;
-    @Autowired
+    @Resource
     private FdkankanMiniClient fdkankanMiniClient;
     @Autowired
     private ISceneUploadService sceneUploadService;
@@ -164,6 +172,9 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
             sceneEditControlsDb = sceneEditControlsService.getBySceneEditId(sceneEditInfoDb.getId());
         }
 
+        //用户上传的文件后缀名转小写
+        this.lowercaseExtName(param);
+
         SceneEditInfo sceneEditInfo = BeanUtil.copyProperties(param, SceneEditInfo.class);
         sceneEditInfo.setScenePlusId(scenePlus.getId());
         if(Objects.isNull(sceneEditInfoDb)){
@@ -191,6 +202,21 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         return result;
     }
 
+    private void lowercaseExtName(SceneEditInfoParamVO sceneEditInfo){
+        if(StrUtil.isNotEmpty(sceneEditInfo.getMusic())){
+            String extName = cn.hutool.core.io.FileUtil.extName(sceneEditInfo.getMusic());
+            if(StrUtil.isNotEmpty(extName)){
+                sceneEditInfo.setMusic(sceneEditInfo.getMusic().replace(extName, extName.toLowerCase()));
+            }
+        }
+        if(StrUtil.isNotEmpty(sceneEditInfo.getMusicFile())){
+            String extName = cn.hutool.core.io.FileUtil.extName(sceneEditInfo.getMusicFile());
+            if(StrUtil.isNotEmpty(extName)){
+                sceneEditInfo.setMusicFile(sceneEditInfo.getMusicFile().replace(extName, extName.toLowerCase()));
+            }
+        }
+    }
+
     @Override
     public SceneEditInfo getBySceneProId(long sceneProId) {
         return this.getOne(new LambdaQueryWrapper<SceneEditInfo>()
@@ -244,6 +270,9 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
             sceneJson.setVideos(scenePlusExt.getVideos());
         }
 
+        //发布马赛克列表
+        sceneJson.setMosaicList(this.getMosaicList(num));
+
         //处理热点数据,生成hot.json
         this.publicHotData(num, sceneEditInfo);
 
@@ -442,6 +471,7 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         sceneInfoVO.setSceneFrom(scenePlusExt.getSceneFrom());
         sceneInfoVO.setSceneKind(scenePlusExt.getSceneKind());
         sceneInfoVO.setVideos(scenePlusExt.getVideos());
+        sceneInfoVO.setMosaicList(this.getMosaicList(num));
 
         // TODO: 2022/4/24 v3版本停机要切换---------------------------start
 //        this.setExtData(sceneInfoVO, scenePlus.getCameraId());
@@ -491,8 +521,8 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         if(sceneProV3.getRecStatus().equals("I")){
             throw new BusinessException(ErrorCode.FAILURE_CODE_5009);
         }
-        if(SceneStatus.SUCCESS.code() != sceneProV3.getStatus()
-            && SceneStatus.NO_DISPLAY.code() != sceneProV3.getStatus()){
+        if((SceneStatus.SUCCESS.code() != sceneProV3.getStatus() && SceneStatus.NO_DISPLAY.code() != sceneProV3.getStatus())
+        || (sceneProV3.getIsUpgrade() != null && sceneProV3.getIsUpgrade()== 2)){
             throw new BusinessException(ErrorCode.FAILURE_CODE_5033);
         }
         if(PayStatus.PAY.code() != sceneProV3.getPayStatus()){
@@ -601,6 +631,11 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         //写入数据库
         Byte floorPlanUser = null;
         if(StrUtil.isNotEmpty(floorJsonData)){
+            // TODO: 2022/7/26 生成hostType
+            JSONObject houseTypeJson = CreateHouseJsonUtil
+                .createHouseTypeJsonByUser(localDataPath + "floorplan_user.json");
+            uploadToOssUtil.upload(houseTypeJson.toJSONString().getBytes(), editUserPath + "houseType.json");
+
             floorPlanUser = CommonStatus.YES.code();
         }
         SceneEditInfo sceneEditInfoDb = this.getByScenePlusId(scenePlus.getId());
@@ -638,7 +673,7 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
     }
 
     @Override
-    public ResultData resetCad(String num){
+    public ResultData resetCad(String num) throws IOException {
 
         ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num);
         if(Objects.isNull(scenePlus))
@@ -660,6 +695,9 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
             });
         }
 
+        //根据floorplan_cad.json生成houseType.json
+        this.uploadHouseTypeJson(num);
+
         ScenePro scenePro = sceneProService.findBySceneNum(num);
         SceneEditInfo sceneEditInfoDb = this.getByScenePlusId(scenePlus.getId());
         SceneEditInfoExt sceneEditInfoExt = null;
@@ -692,6 +730,112 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
 
     }
 
+    private void uploadHouseTypeJson(String num) throws IOException {
+
+        JSONObject result = new JSONObject();
+        result.put("name", "houseType.json");
+        result.put("version", "2.1");
+
+        String floorplanCadPath = String.format(UploadFilePath.DATA_VIEW_PATH, num) + "floorplan_cad.json";
+        String floorcadStr = uploadToOssUtil.getObjectContent(this.bucket, floorplanCadPath);
+
+        JSONObject floorcadObj = JSON.parseObject(floorcadStr);
+        JSONArray floors = floorcadObj.getJSONArray("floors");
+
+        JSONArray targetFloors = new JSONArray();
+        result.put("floors", targetFloors);
+        for(int i = 0; i < floors.size(); i++){
+            JSONObject floor = (JSONObject)floors.get(i);
+            JSONArray[] pointsAndWalls = this.createHouseTypeJsonHandler(floor);
+            JSONArray points = pointsAndWalls[0];
+            JSONArray walls = pointsAndWalls[1];
+            JSONObject targetFloor = new JSONObject();
+            targetFloor.put("points", points);
+            targetFloor.put("walls", walls);
+            targetFloors.add(targetFloor);
+        }
+
+        String hourseTypeJsonPath = String.format(UploadFilePath.USER_EDIT_PATH, num) + "houseType.json";
+        uploadToOssUtil.upload(result.toJSONString().getBytes(), hourseTypeJsonPath);
+    }
+
+    private JSONArray[] createHouseTypeJsonHandler(JSONObject floor){
+
+        JSONArray[] result = new JSONArray[2];
+
+        //处理点
+        Map<Integer, VertexBean> vertexMap = new HashMap<>();
+        Map<String, PointBean> pointMap = new HashMap<>();
+        Map<Integer, String> vpMap = new HashMap<>();
+        JSONArray vertexArr = floor.getJSONArray("vertex-xy");
+        for(int i = 0; i < vertexArr.size(); i++){
+            Object o = vertexArr.get(i);
+
+            VertexBean vertexBean = JSON.parseObject(JSON.toJSONString(o), VertexBean.class);
+            Integer vertexId = vertexBean.getId();
+            vertexMap.put(vertexId, vertexBean);
+
+            String pointId = "Point" + i;
+            pointMap.put(pointId, PointBean.builder().vectorId(pointId).x(vertexBean.getX()).y(vertexBean.getY()).build());
+
+            vpMap.put(vertexId, pointId);
+        }
+
+        //处理墙
+        Map<Integer, SegmentBean> segmentMap = new HashMap<>();
+        Map<String, WallBean> wallMap = new HashMap<>();
+        Map<Integer, String> swMap = new HashMap<>();
+        JSONArray segmentArr = floor.getJSONArray("segment");
+        Map<String, String> startMap = new HashMap<>();
+        Map<String, String> endMap = new HashMap<>();
+        for(int i = 0; i < segmentArr.size(); i++){
+            Object o = segmentArr.get(i);
+
+            SegmentBean segmentBean = JSON.parseObject(JSON.toJSONString(o), SegmentBean.class);
+            String startPointId = vpMap.get(segmentBean.getA());
+            String endPointId = vpMap.get(segmentBean.getB());
+            segmentBean.setStartPointId(startPointId);
+            segmentBean.setEndPointId(endPointId);
+
+            Integer segmentId = segmentBean.getId();
+            segmentMap.put(segmentId, segmentBean);
+
+            String wallId = "Wall" + i;
+            WallBean wallBean = WallBean.builder()
+                .vectorId(wallId)
+                .start(segmentBean.getStartPointId())
+                .end(segmentBean.getEndPointId())
+                .children(new String[]{})
+                .width(0.2d)
+                .build();
+            wallMap.put(wallId, wallBean);
+
+            startMap.put(wallBean.getStart(), wallBean.getVectorId());
+            endMap.put(wallBean.getEnd(), wallBean.getVectorId());
+
+            swMap.put(segmentId, wallId);
+        }
+
+        Collection<PointBean> pointBeans = pointMap.values();
+        for (PointBean pointBean : pointBeans) {
+            Map<String, String> parent = new HashMap<>();
+            String startParent = startMap.get(pointBean.getVectorId());
+            String endParent = endMap.get(pointBean.getVectorId());
+            parent.put(startParent, "start");
+            parent.put(endParent, "end");
+            pointBean.setParent(parent);
+        }
+        JSONArray pointArr = JSON.parseArray(JSON.toJSONString(pointBeans));
+        result[0] = pointArr;
+
+        Collection<WallBean> wallBeans = wallMap.values();
+        JSONArray wallArr = JSON.parseArray(JSON.toJSONString(wallBeans));
+        result[1] = wallArr;
+
+        return result;
+
+    }
+
     @Override
     public ResultData renameCad(RenameCadParamVO param) throws IOException {
 
@@ -753,7 +897,15 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
     }
 
     @Override
-    public void upgradeSceneJsonVersion(String num, int version) throws IOException {
+    public void upgradeVersionAndImgVersionById(Long id) {
+        this.update(new LambdaUpdateWrapper<SceneEditInfo>()
+            .setSql("version=version + " + 1)
+            .setSql("img_version=img_version + " + 1)
+            .eq(SceneEditInfo::getId, id));
+    }
+
+    @Override
+    public void upgradeSceneJsonVersion(String num, int version, Integer imgVersion) throws IOException {
 
         //更新redis缓存版本号
         String key = String.format(RedisKey.SCENE_JSON, num);
@@ -761,6 +913,9 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         if(StrUtil.isNotEmpty(sceneJson)){
             SceneJsonBean sceneJsonBean = JSON.parseObject(sceneJson, SceneJsonBean.class);
             sceneJsonBean.setVersion(version);
+            if(Objects.nonNull(imgVersion)){
+                sceneJsonBean.setImgVersion(imgVersion + 1);
+            }
             redisUtil.set(key, JSON.toJSONString(sceneJsonBean));
         }
 
@@ -770,6 +925,9 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         if(StrUtil.isNotEmpty(sceneJson)){
             SceneJsonBean sceneJsonBean = JSON.parseObject(sceneJson, SceneJsonBean.class);
             sceneJsonBean.setVersion(version);
+            if(Objects.nonNull(imgVersion)){
+                sceneJsonBean.setImgVersion(imgVersion + 1);
+            }
             uploadToOssUtil.upload(JSON.toJSONString(sceneJsonBean).getBytes(StandardCharsets.UTF_8), sceneJsonPath);
         }
 
@@ -1007,9 +1165,9 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
 
         //更新数据库版本号
         SceneEditInfo sceneEditInfo = this.getByScenePlusId(scenePlus.getId());
-        this.upgradeVersionById(sceneEditInfo.getId());
+        this.upgradeVersionAndImgVersionById(sceneEditInfo.getId());
         //更新scenejson缓存和oss文件版本号
-        this.upgradeSceneJsonVersion(num, sceneEditInfo.getVersion() + 1);
+        this.upgradeSceneJsonVersion(num, sceneEditInfo.getVersion() + 1, sceneEditInfo.getImgVersion() + 1);
 
         //如果部分成功,则需要返回成功数量和失败列表
         if(CollUtil.isNotEmpty(notExistFileList)){
@@ -1081,13 +1239,18 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
             }
 
             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));
             //上传压缩包
 //            uploadToOssUtil.upload(zipPath, String.format(cacheFormat, num) + downloadName);
             uploadToOssUtil.uploadBySh(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);
 //            //删除本地目录
@@ -1300,7 +1463,7 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         //更新scene.json版本号
 //        this.upgradeVersionToSceneJson(num);
         //更新scenejson缓存和oss文件版本号
-        this.upgradeSceneJsonVersion(num, sceneEditInfo.getVersion() + 1);
+        this.upgradeSceneJsonVersion(num, sceneEditInfo.getVersion() + 1, null);
 
         return ResultData.ok();
     }
@@ -1504,172 +1667,117 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
     @Override
     public ResultData addMosaics(BaseDataParamVO param) throws Exception {
 
-        JSONArray mosaicArr = JSONArray.parseArray(param.getData());
-        if (CollUtil.isEmpty(mosaicArr) || mosaicArr.size() > 1) {
-            throw new BusinessException(ErrorCode.FAILURE_CODE_5012);
-        }
-        JSONObject mosicObj= mosaicArr.getJSONObject(0);
+        //如果redis数据丢失,从本地文件中同步马赛克数据到redis
+        this.syncMosaicFromFileToRedis(param.getNum());
 
-        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
-        if(Objects.isNull(scenePlus)){
-            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
+        Map<String, String> map = new HashMap<>();
+        JSONArray jsonArray = JSON.parseArray(param.getData());
+        for (Object o : jsonArray) {
+            JSONObject mosaic = (JSONObject) o;
+            String panoId = mosaic.getString("panoId");
+            if(StrUtil.isEmpty(panoId)){
+                throw  new BusinessException(ErrorCode.FAILURE_CODE_5012);
+            }
+            map.put(panoId, JSON.toJSONString(mosaic));
         }
-        ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
-        SceneEditInfo sceneEditInfo = this.getByScenePlusId(scenePlus.getId());
-        SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByEditInfoId(sceneEditInfo.getId());
-
-        String dataViewPath = String.format(UploadFilePath.DATA_VIEW_PATH, param.getNum());
-        String imgViewPath = String.format(UploadFilePath.IMG_VIEW_PATH, param.getNum());
+        String key = String.format(RedisKey.SCENE_MOSAIC_DATA, param.getNum());
+        redisUtil.hmset(key, map);
 
-        String path = scenePlusExt.getDataSource();
-        if(StrUtil.isNotEmpty(path) && path.startsWith("http")){
-            path = ConstantFilePath.BUILD_MODEL_PATH + File.separator + path.split("/")[path.split("/").length - 2];
-        }
-        String target = path + "_roi";
+        //写入本地文件,作为备份
+        this.writeMosaic(param.getNum());
 
-        cn.hutool.core.io.FileUtil.del(target);
+        //更新数据库
+        this.updateMosaicFlag(param.getNum());
 
-        //文件上传的位置可以自定义
-        String filePath = target + File.separator + "extras" + File.separator + "images/";
-        File imageFile = new File(filePath);
-        if(!imageFile.getParentFile().exists()){
-            imageFile.getParentFile().mkdirs();
-        }
-        FileUtils.copyFolderAllFiles(path + "/caches/images/", filePath, true);
+        return ResultData.ok();
+    }
 
-        String mosaicData = sceneEditInfoExt.getMosaics();
-        JSONArray jsonArray = new JSONArray();
-        if(StrUtil.isNotEmpty(mosaicData)){
-            jsonArray = JSONArray.parseArray(mosaicData);
-        }
-        jsonArray.add(mosicObj);
+    private void updateMosaicFlag(String num){
+        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num);
+        SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByScenePlusId(scenePlus.getId());
 
-        // 准备算法数据
-        List<JSONObject> mosaicsList = new ArrayList<>();
-        for(int i = 0, len = jsonArray.size(); i < len; i++){
-            JSONObject jsonObject = jsonArray.getJSONObject(i);
-            boolean contains = false;
-            for (JSONObject item : mosaicsList) {
-                if(StringUtils.equals(item.getString("panoId"),jsonObject.getString("panoId"))){
-                    contains = true;
-                    item.getJSONArray("rect").addAll(jsonObject.getJSONArray("rect"));
-                }
-            }
-            if(!contains){
-                mosaicsList.add(jsonObject);
-            }
+        String key = String.format(RedisKey.SCENE_MOSAIC_DATA, num);
+        boolean flag = redisUtil.hasKey(key);
+        if(flag){
+            sceneEditInfoExt.setMosaic(Integer.valueOf(CommonStatus.YES.code()));
+        }else{
+            sceneEditInfoExt.setMosaic(Integer.valueOf(CommonStatus.NO.code()));
         }
-        JSONObject roiImageJSon = new JSONObject();
-        roiImageJSon.put("batch",mosaicsList);
-
-        FileUtils.writeFile(target + File.separator + "extras" + File.separator + "image-ROI.json", JSON.toJSONString(roiImageJSon,SerializerFeature.DisableCircularReferenceDetect));
+        sceneEditInfoExtService.updateById(sceneEditInfoExt);
+    }
 
-        FileUtils.copyFile(path + File.separator + "results/vision.txt", target + File.separator+"extras/vision.txt", true);
-        FileUtils.copyFile(path + File.separator + "results/vision2.txt", target + File.separator+"extras/vision2.txt", true);
-        FileUtils.copyFile(path + File.separator + "data.json", target + File.separator+"data.json", true);
-        String data = FileUtils.readFile(target + File.separator+"data.json");
-        if(data != null){
-            JSONObject floorplanJson = new JSONObject();
-            floorplanJson.put("has_source_images", true);
-            floorplanJson.put("has_vision_txt", true);
+    /**
+     * <p>
+     保证马赛克数据安全性,当redis宕机导致热点数据丢失时,可以从文件中读取,恢复到redis
+     **/
+    private void syncMosaicFromFileToRedis(String num) throws Exception{
 
-            JSONObject dataJson = JSONObject.parseObject(data);
-            dataJson.put("extras", floorplanJson);
-            //V5表示不需要生成high,low文件
-            dataJson.put("skybox_type", "SKYBOX_V6");
-            if(scenePlusExt.getSceneScheme() == 11){
-                dataJson.put("skybox_type", "SKYBOX_V7");
-            }
-            dataJson.put("split_type", "SPLIT_V18");
-            //sceneScheme为3切成瓦片图
-            if(scenePlusExt.getSceneScheme() == 3){
-                dataJson.put("skybox_type", "SKYBOX_V4");
-            }
-            FileUtils.writeFile(target + File.separator+"data.json", new String(dataJson.toString().getBytes(), "UTF-8"));
+        String key = String.format(RedisKey.SCENE_MOSAIC_DATA, num);
+        boolean exist = redisUtil.hasKey(key);
+        if(exist){
+            return;
         }
-
-        FileUtils.copyFile(path + File.separator + "project.json", target + File.separator+"project.json", true);
-
-        //进行计算
-        log.info("马赛克建模开始, num:{}, path:{}" + param.getNum(), target);
-        CreateObjUtil.build3dModel2(target , "1");
-        log.info("马赛克建模结束, num:{}, path:{}" + param.getNum(), target);
-
-        //读取upload文件,检验需要上传的文件是否存在
-        String uploadJsonPath = target + File.separator + "results" + File.separator + "upload.json";
-        boolean exist = ComputerUtil.checkComputeCompleted(uploadJsonPath, maxCheckTimes, waitTime);
-        if(!exist){
-            throw new BusinessException(ErrorCode.FAILURE_CODE_5042);
+        String lockKey = String.format(RedisLockKey.LOCK_MOSAIC_DATA_SYNC, num);
+        boolean lock = redisLockUtil.lock(lockKey, RedisKey.EXPIRE_TIME_1_MINUTE);
+        if(!lock){
+            throw new BusinessException(ErrorCode.SYSTEM_BUSY);
         }
-        String uploadData = FileUtils.readFile(target + File.separator + "results" + File.separator + "upload.json");
-        JSONObject uploadJson = JSONObject.parseObject(uploadData);
-        JSONArray array = uploadJson.getJSONArray("upload");
-        Map<String,String> map = new HashMap<>();
-        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(target + File.separator + "results" +File.separator + fileName).exists()){
-                throw new Exception(target + File.separator + "results" +File.separator + fileName+"文件不存在");
-            }
-
-            //high文件夹
-            if(fileJson.getIntValue("clazz") == 3){
-                map.put(target + File.separator + "results" +File.separator+ fileName,
-                    imgViewPath + "pan/high/"+ fileName.replace("high/", ""));
+        try{
+            exist = redisUtil.hasKey(key);
+            if(exist){
+                return;
             }
-            //low文件夹
-            if(fileJson.getIntValue("clazz") == 4){
-                map.put(target + File.separator + "results" +File.separator+ fileName,
-                    imgViewPath + "pan/low/"+ fileName.replace("low/", ""));
+            String filePath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num);
+            String mosaicData = FileUtils.readFile(filePath + "mosaic.json");
+            if(StrUtil.isEmpty(mosaicData)){
+                return;
             }
-
-            //tiles文件夹,亚马逊没有裁剪图片api,不需要上传4k图
-            if(fileJson.getIntValue("clazz") == 5){
-                map.put(target + File.separator + "results" + File.separator+ fileName,
-                    imgViewPath + fileName);
+            JSONArray jsonArray = JSON.parseArray(mosaicData);
+            if(CollUtil.isEmpty(jsonArray)){
+                return;
             }
-
-            //tiles文件夹,亚马逊瓦片图
-            if(fileJson.getIntValue("clazz") == 7 ){
-                map.put(target + File.separator + "results" + File.separator+ fileName,
-                    imgViewPath + fileName);
+            Map<String, String> map = new HashMap<>();
+            for (Object o : jsonArray) {
+                JSONObject jo = (JSONObject)o;
+                map.put(jo.getString("panoId"), jo.toJSONString());
             }
+            redisUtil.hmset(key, map);
+        }finally {
+            redisLockUtil.unlockLua(lockKey);
         }
+    }
 
-        for(String imagesName : imageFile.list()){
-            //覆盖原始图片资源
-            FileUtils.copyFile(target + File.separator + "extras/images/" + imagesName,
-                path + File.separator + "caches/images/" + imagesName, true);
-            FileUtils.deleteFile(target + File.separator + "extras/images/" + imagesName);
-        }
-
-        uploadToOssUtil.uploadMulFiles(map);
-
-        this.upgradeVersionById(sceneEditInfo.getId());
+    /**
+     * <p>
+     保证马赛克数据安全性,当redis宕机导致热点数据丢失时,可以从文件中读取,恢复到redis
+     **/
+    private void writeMosaic(String num) throws Exception{
 
-        sceneEditInfoExt.setMosaics(JSON.toJSONString(jsonArray,SerializerFeature.DisableCircularReferenceDetect));
-        sceneEditInfoExtService.updateById(sceneEditInfoExt);
+        String mosaicPath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + "mosaic.json";
 
-        // 更新 scene.json
-        String sceneJsonPath = dataViewPath + "scene.json";
-        String sceneJson = uploadToOssUtil.getObjectContent(this.bucket, sceneJsonPath);
-        JSONObject scenejson = new JSONObject();
-        if(StrUtil.isNotEmpty(sceneJson)) {
-            scenejson = JSONObject.parseObject(sceneJson);
+        String key = String.format(RedisKey.SCENE_MOSAIC_DATA, num);
+        Map<String, String> mosaicMap = redisUtil.hmget(key);
+        if(CollUtil.isEmpty(mosaicMap)){
+            FileUtils.deleteFile(mosaicPath);
+            return;
         }
-        scenejson.put("mosaics",JSON.toJSONString(jsonArray, SerializerFeature.DisableCircularReferenceDetect));
-        Integer version = scenejson.getIntValue("version");
-        version = Objects.isNull(version) ? 1 : version + 1;
-        scenejson.put("version", version);
-        uploadToOssUtil.upload(scenejson.toJSONString().getBytes(), sceneJsonPath);
+        List<String> mosaicList = Lists.newArrayList(mosaicMap.values());
+        JSONArray jsonArr = new JSONArray();
+        mosaicList.stream().forEach(mosaic->{
+            jsonArr.add(JSONObject.parseObject(mosaic));
+        });
 
-        Map<String,Object> result = new HashMap<>(1);
-        result.put("mosaics",jsonArray);
 
-        return ResultData.ok(result);
+        String lockKey = String.format(RedisLockKey.LOCK_MOSAIC_JSON, num);
+        boolean lock = redisLockUtil.lock(lockKey, RedisKey.EXPIRE_TIME_1_MINUTE);
+        if(!lock){
+            return;
+        }
+        try{
+            FileUtils.writeFile(mosaicPath, jsonArr.toJSONString());
+        }finally {
+            redisLockUtil.unlockLua(lockKey);
+        }
     }
 
     @Override
@@ -2000,7 +2108,10 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
                 .eq(SceneEditInfoExt::getEditInfoId, sceneEditInfo.getId()));
 
         //更新场景版本
-        this.upgradeVersionById(sceneEditInfo.getId());
+        this.update(new LambdaUpdateWrapper<SceneEditInfo>()
+            .setSql("version=version+" + 1)
+            .setSql("link_version=link_version+" + 1)
+            .eq(SceneEditInfo::getId, sceneEditInfo.getId()));
     }
 
     /**
@@ -2402,4 +2513,70 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         uploadToOssUtil.upload(localFilePath.replace("mp4", "flv"), userEditPath+flvFileName);
     }
 
+    @Override
+    public ResultData deleteMosaics(DeleteMosaicParamVO param) throws Exception {
+
+        //如果redis数据丢失,从本地文件中同步马赛克数据到redis
+        this.syncMosaicFromFileToRedis(param.getNum());
+
+        String key = String.format(RedisKey.SCENE_MOSAIC_DATA, param.getNum());
+        redisUtil.hdel(key, param.getPanoIdList().toArray());
+
+        //写入本地文件,作为备份
+        this.writeMosaic(param.getNum());
+
+        //更新数据库
+        this.updateMosaicFlag(param.getNum());
+
+        return ResultData.ok();
+    }
+
+    @Override
+    public List<JSONObject> getMosaicList(String num) throws Exception {
+
+        //如果redis数据丢失,从本地文件中同步马赛克数据到redis
+        this.syncMosaicFromFileToRedis(num);
+
+        String key = String.format(RedisKey.SCENE_MOSAIC_DATA, num);
+        Map<String, String> map = redisUtil.hmget(key);
+        if(CollUtil.isEmpty(map)){
+            ResultData.ok(new String[0]);
+        }
+        return map.values().stream()
+                .map(mosaic-> JSON.parseObject(mosaic))
+                .collect(Collectors.toList());
+
+    }
+
+    @Override
+    public ResultData addWaterMark(BaseFileParamVO param) throws Exception {
+        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
+        if(Objects.isNull(scenePlus)){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
+        }
+        SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService
+            .getByScenePlusId(scenePlus.getId());
+        sceneEditInfoExt.setWaterMark(param.getFileName());
+        sceneEditInfoExtService.updateById(sceneEditInfoExt);
+        return ResultData.ok();
+    }
+
+    @Override
+    public ResultData deleteWaterMark(BaseFileParamVO param) throws Exception {
+        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
+        if(Objects.isNull(scenePlus)){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
+        }
+        sceneUploadService.delete(
+            DeleteFileParamVO.builder()
+                .num(param.getNum())
+                .fileNames(Lists.newArrayList(param.getFileName()))
+                .bizType(FileBizType.WATERMARK.code()).build());
+
+        SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByScenePlusId(scenePlus.getId());
+        sceneEditInfoExt.setWaterMark("");
+        sceneEditInfoExtService.updateById(sceneEditInfoExt);
+
+        return ResultData.ok();
+    }
 }

+ 2 - 1
4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/SceneEditServiceImpl.java

@@ -93,7 +93,8 @@ public class SceneEditServiceImpl implements ISceneEditService {
             throw new BusinessException(ErrorCode.FAILURE_CODE_5009);
         }
         if(SceneStatus.SUCCESS.code() != sceneProV3.getStatus()
-            && SceneStatus.NO_DISPLAY.code() != sceneProV3.getStatus()){
+            && SceneStatus.NO_DISPLAY.code() != sceneProV3.getStatus()
+            || (sceneProV3.getIsUpgrade() != null && sceneProV3.getIsUpgrade()== 2)){
             throw new BusinessException(ErrorCode.FAILURE_CODE_5033);
         }
         if(PayStatus.PAY.code() != sceneProV3.getPayStatus()){

+ 4 - 2
4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/SceneProServiceImpl.java

@@ -105,6 +105,7 @@ import java.util.Set;
 import java.util.UUID;
 import java.util.stream.Collectors;
 import javax.annotation.Resource;
+import java.nio.charset.StandardCharsets;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.joda.time.DateTime;
@@ -3126,7 +3127,7 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
         }else{
             sceneEditInfoService.upgradeVersionById(editInfo.getId());
             //更新scenejson缓存和oss文件版本号
-            sceneEditInfoService.upgradeSceneJsonVersion(param.getNum(), editInfo.getVersion() + 1);
+            sceneEditInfoService.upgradeSceneJsonVersion(param.getNum(), editInfo.getVersion() + 1, null);
         }
 
         //更新scene.json版本号
@@ -3578,10 +3579,11 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
                     .setSql("version = version + 1")
                     .setSql("floor_edit_ver = floor_edit_ver + 1")
                     .setSql("floor_publish_ver = floor_publish_ver + 1")
+                    .setSql("img_version = img_version + 1")
                     .set(SceneEditInfo::getIsUploadObj, CommonStatus.YES.code())
                     .eq(SceneEditInfo::getId, sceneEditInfo.getId()));
 
-            sceneEditInfoService.upgradeSceneJsonVersion(num, sceneEditInfo.getVersion() + 1);
+            sceneEditInfoService.upgradeSceneJsonVersion(num, sceneEditInfo.getVersion() + 1, sceneEditInfo.getImgVersion() + 1);
         }
 
         return ResultData.ok();

+ 65 - 10
4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/SceneServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -28,6 +29,7 @@ import com.fdkankan.common.response.ResultData;
 import com.fdkankan.common.util.ConvertUtils;
 import com.fdkankan.common.util.DateExtUtil;
 import com.fdkankan.common.util.FileUtils;
+import com.fdkankan.common.util.MatrixToImageWriterUtil;
 import com.fdkankan.fyun.oss.UploadToOssUtil;
 import com.fdkankan.fyun.qiniu.QiniuUpload;
 import com.fdkankan.redis.constant.RedisKey;
@@ -46,6 +48,8 @@ import com.fdkankan.scene.entity.ScenePlusExt;
 import com.fdkankan.scene.entity.ScenePro;
 import com.fdkankan.scene.entity.SceneProExt;
 import com.fdkankan.scene.entity.SceneProPO;
+import com.fdkankan.scene.bean.SceneJsonBean;
+import com.fdkankan.scene.entity.*;
 import com.fdkankan.scene.mapper.ISceneMapper;
 import com.fdkankan.scene.mapper.ISceneProMapper;
 import com.fdkankan.scene.service.ISceneDataDownloadService;
@@ -139,6 +143,12 @@ public class SceneServiceImpl extends ServiceImpl<ISceneMapper, Scene> implement
     @Autowired
     private ISceneDataDownloadService sceneDataDownloadService;
 
+    @Value("${main.url}")
+    private String mainUrl;
+
+    @Value("${scene.pro.new.url}")
+    private String sceneProNewUrl;
+
     @Override
     public void updateUserIdByCameraId(Long userId, Long cameraId) {
         this.update(new LambdaUpdateWrapper<Scene>().eq(Scene::getCameraId, cameraId).set(Scene::getUserId, userId));
@@ -1319,7 +1329,7 @@ public class SceneServiceImpl extends ServiceImpl<ISceneMapper, Scene> implement
     }
 
     @Override
-    public void copyScene(CopySceneParamVO paramVO) throws IOException {
+    public void copyScene(CopySceneParamVO paramVO) throws Exception {
         String num = paramVO.getOldNum();
         String newNum = paramVO.getNewNum();
 
@@ -1332,31 +1342,41 @@ public class SceneServiceImpl extends ServiceImpl<ISceneMapper, Scene> implement
         String oldEditPath = String.format(UploadFilePath.EDIT_PATH, num);
 
         String newEditPath = String.format(UploadFilePath.EDIT_PATH, newNum);
-        uploadToOssUtil.copyFiles(oldEditPath,newEditPath);
+        uploadToOssUtil.copyFiles(oldEditPath, newEditPath);
 
         // 拷贝场景展示资源
         String oldViewPath = String.format(UploadFilePath.VIEW_PATH, num);
         String newViewPath = String.format(UploadFilePath.VIEW_PATH, newNum);
-        uploadToOssUtil.copyFiles(oldViewPath,newViewPath);
+        uploadToOssUtil.copyFiles(oldViewPath, newViewPath);
 
         // 拷贝本地资源
         String oldPath = String.format("/mnt/4Dkankan/scene/%s/caches/images/", num);
         String newPath = String.format("/mnt/4Dkankan/scene/%s/caches/images/", newNum);
-        FileUtils.copyDirectiory(oldPath,newPath);
+        if(new File(oldPath).exists()){
+            FileUtils.copyDirectiory(oldPath, newPath);
+        }
+
+        String scenePath = ConstantFilePath.SCENE_V4_PATH + num;
+        File file = new File(scenePath);
+        if(file.exists()){
+            String newScenePath = ConstantFilePath.SCENE_V4_PATH + newNum;
+            FileUtils.copyDirectiory(scenePath, newScenePath);
+        }
 
         // 拷贝数据
         Long proId = scenePro.getId();
         scenePro.setId(paramVO.getNewSceneProId());
-        scenePro.setWebSite(scenePro.getWebSite().replace(num,newNum));
+        scenePro.setWebSite(scenePro.getWebSite().replace(num, newNum));
         scenePro.setSceneName(paramVO.getNewSceneName());
-        scenePro.setThumb(scenePro.getThumb().replace(num,newNum));
-        scenePro.setVideos(scenePro.getVideos().replaceAll("https://4dkk.4dage.com/data/data"+num,"https://4dkk.4dage.com/scene_view_data/"+newNum+"/data"));
+        scenePro.setThumb(scenePro.getThumb().replace(num, newNum));
+        scenePro.setVideos(scenePro.getVideos().replaceAll("https://4dkk.4dage.com/data/data" + num, "https://4dkk.4dage.com/scene_view_data/" + newNum + "/data"));
         scenePro.setNum(newNum);
         sceneProService.saveOrUpdate(scenePro);
 
         SceneProExt proExt = sceneProExtService.findBySceneProId(proId);
         proExt.setDataSource(paramVO.getDatasource());
         proExt.setId(null);
+        proExt.setViewCount(0);
         proExt.setSceneProId(scenePro.getId());
         sceneProExtService.save(proExt);
 
@@ -1371,9 +1391,9 @@ public class SceneServiceImpl extends ServiceImpl<ISceneMapper, Scene> implement
         plusExt.setId(null);
         plusExt.setPlusId(scenePlus.getId());
         plusExt.setDataSource(paramVO.getDatasource());
-        plusExt.setWebSite(plusExt.getWebSite().replace(num,newNum));
-        plusExt.setThumb(plusExt.getThumb().replace(num,newNum));
-        plusExt.setVideos(plusExt.getVideos().replace(num,newNum));
+        plusExt.setWebSite(plusExt.getWebSite().replace(num, newNum));
+        plusExt.setThumb(plusExt.getThumb().replace(num, newNum));
+        plusExt.setVideos(scenePro.getVideos());
         scenePlusExtService.save(plusExt);
 
         SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(plusId);
@@ -1397,5 +1417,40 @@ public class SceneServiceImpl extends ServiceImpl<ISceneMapper, Scene> implement
         sceneEditControls.setEditInfoId(sceneEditInfo.getId());
         sceneEditControlsService.save(sceneEditControls);
 
+        // 生成scene.json
+        SceneJsonBean sceneJson = new SceneJsonBean();
+        BeanUtil.copyProperties(sceneEditInfoExt, sceneJson);
+        BeanUtil.copyProperties(sceneEditInfo, sceneJson);
+        SceneEditControlsVO sceneEditControlsVO = BeanUtil.copyProperties(sceneEditControls, SceneEditControlsVO.class);
+        sceneJson.setControls(sceneEditControlsVO);
+        sceneJson.setNum(newNum);
+        sceneJson.setCreateTime(scenePlus.getCreateTime());
+
+        sceneJson.setSceneResolution(plusExt.getSceneResolution());
+        sceneJson.setSceneFrom(plusExt.getSceneFrom());
+        sceneJson.setSceneKind(plusExt.getSceneKind());
+        if(StrUtil.isNotEmpty(plusExt.getVideos())){
+            sceneJson.setVideos(plusExt.getVideos());
+        }
+
+        log.info("开始生成本地json文件……");
+        String sceneJsonLocalPath = ConstantFilePath.SCENE_PATH + "data" + File.separator + "data" + newNum + File.separator + "scene.json";
+        FileUtils.writeFile(sceneJsonLocalPath,JSON.toJSONString(sceneJson));
+
+        String sceneJsonPath = String.format(UploadFilePath.DATA_VIEW_PATH+"scene.json", newNum);
+        uploadToOssUtil.upload(JSON.toJSONBytes(sceneJson), sceneJsonPath);
+
+        //删除scenejson缓存
+        redisUtil.del(String.format(RedisKey.SCENE_JSON, num));
+
+
+        // 生成二维码
+        String sceneUrl = mainUrl + "/" + sceneProNewUrl;
+        String outPathZh = ConstantFilePath.BASE_PATH + File.separator + "sceneQRcode/" + newNum + ".png";
+        String outPathEn = ConstantFilePath.BASE_PATH + File.separator + "sceneQRcode/" + newNum + "_en.png";
+        MatrixToImageWriterUtil.createQRCode(sceneUrl + newNum, outPathZh, false,null);
+        MatrixToImageWriterUtil.createQRCode(sceneUrl + newNum + "&lang=en", outPathEn, false, null);
+        uploadToOssUtil.upload(outPathZh, String.format(UploadFilePath.DOWNLOADS_QRCODE, newNum) + newNum + ".png");
+        uploadToOssUtil.upload(outPathEn, String.format(UploadFilePath.DOWNLOADS_QRCODE, newNum) + newNum + "_en.png");
     }
 }

+ 5 - 0
4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/SceneUploadServiceImpl.java

@@ -132,6 +132,11 @@ public class SceneUploadServiceImpl extends ServiceImpl<ISceneUploadMapper, Scen
             if(files.size() ==1 && StringUtils.isNotBlank(sendFileName)){
                 realFileName = sendFileName ;
             }
+
+            String oldExtName = cn.hutool.core.io.FileUtil.extName(realFileName);
+            String newExtName = oldExtName.toLowerCase();
+            realFileName = realFileName.substring(0, realFileName.lastIndexOf(oldExtName)) + newExtName;
+
             String ossPath = StrUtil.isNotBlank(uploadPath) ? uploadPath : (String.format(UploadFilePath.USER_EDIT_PATH ,sceneCode) + realFileName);
             try {
                 uploadToOssUtil.upload2(newFile.getPath(),ossPath);

+ 1 - 0
4dkankan-center-scene/src/main/java/com/fdkankan/scene/vo/BaseDataParamVO.java

@@ -1,5 +1,6 @@
 package com.fdkankan.scene.vo;
 
+import com.fdkankan.redis.constant.RedisKey;
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
 import lombok.Data;

+ 28 - 0
4dkankan-center-scene/src/main/java/com/fdkankan/scene/vo/DeleteMosaicParamVO.java

@@ -0,0 +1,28 @@
+package com.fdkankan.scene.vo;
+
+import java.util.List;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import lombok.Data;
+
+/**
+ * <p>
+        删除马赛克入参
+ * </p>
+ * @author dengsixing
+ * @date 2022/7/12
+ * @param null
+ * @return null
+ **/
+@Data
+public class DeleteMosaicParamVO {
+
+    @NotBlank(message = "场景码不能为空")
+    private String num;
+
+    @NotNull(message = "panoIdList不能为空")
+    private List<String> panoIdList;
+
+
+
+}

+ 24 - 2
4dkankan-center-scene/src/main/java/com/fdkankan/scene/vo/SceneInfoVO.java

@@ -1,6 +1,8 @@
 package com.fdkankan.scene.vo;
 
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.annotation.TableField;
+import java.util.List;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
@@ -91,6 +93,16 @@ public class SceneInfoVO {
     private Integer version;
 
     /**
+     * 图片版本
+     */
+    private Integer imgVersion;
+
+    /**
+     * 场景关联版本
+     */
+    private Integer linkVersion;
+
+    /**
      * 是否上传了户型图(0-否,1-是)
      */
     private Byte floorPlanUser;
@@ -173,9 +185,19 @@ public class SceneInfoVO {
     private Integer tours;
 
     /**
-     * 马赛克数据
+     * 是否有马赛克
+     */
+    private Integer mosaic;
+
+    /**
+     * 马赛克列表
+     */
+    private List<JSONObject> mosaicList;
+
+    /**
+     * 水印文件名
      */
-    private String mosaics;
+    private String waterMark;
 
     /**
      * 是否有场景关联(0-否,1-是)