package com.fdkankan.scene.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.fdkankan.common.constant.*; import com.fdkankan.common.exception.BusinessException; import com.fdkankan.common.response.ResultData; import com.fdkankan.common.util.CreateObjUtil; import com.fdkankan.common.util.FileMd5Util; import com.fdkankan.common.util.FileUtil; import com.fdkankan.common.util.FileUtils; import com.fdkankan.fyun.constant.StorageType; import com.fdkankan.fyun.oss.UploadToOssUtil; import com.fdkankan.redis.constant.RedisKey; import com.fdkankan.redis.constant.RedisLockKey; import com.fdkankan.redis.util.RedisLockUtil; import com.fdkankan.redis.util.RedisUtil; import com.fdkankan.scene.bean.SceneJsonBean; import com.fdkankan.scene.entity.SceneDataDownload; import com.fdkankan.scene.entity.SceneEditControls; import com.fdkankan.scene.entity.SceneEditInfo; import com.fdkankan.scene.entity.ScenePro; import com.fdkankan.scene.entity.SceneProExt; import com.fdkankan.scene.factory.FloorLogoHandlerFactory; import com.fdkankan.scene.factory.MusicHandlerFactory; import com.fdkankan.scene.factory.ScreenshotHandlerFactory; import com.fdkankan.scene.mapper.ISceneEditInfoMapper; import com.fdkankan.scene.service.ISceneDataDownloadService; import com.fdkankan.scene.service.ISceneEditControlsService; import com.fdkankan.scene.service.ISceneEditInfoService; import com.fdkankan.scene.service.ISceneProExtService; import com.fdkankan.scene.service.ISceneProService; import com.fdkankan.scene.vo.*; import com.google.common.collect.Lists; import com.google.errorprone.annotations.Var; import java.io.File; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.io.IOException; import java.util.Calendar; import java.util.Objects; import org.springframework.web.multipart.MultipartFile; /** *

* 服务实现类 *

* * @author * @since 2022-01-18 */ @Slf4j @Service public class SceneEditInfoServiceImpl extends ServiceImpl implements ISceneEditInfoService { @Value("${oss.prefix.ali}") private String prefixAli; @Value("${oss.prefix.url}") private String ossUrlPrefix; @Value("${upload.type}") private String type; @Value("${oss.bucket:4dkankan}") private String bucket; @Value("${main.url}") private String mainUrl; @Autowired private ISceneEditControlsService sceneEditControlsService; @Autowired private ISceneProService sceneProService; @Autowired private UploadToOssUtil uploadToOssUtil; @Autowired RedisUtil redisUtil; @Autowired private ISceneProExtService sceneProExtService; @Autowired private RedisLockUtil redisLockUtil; @Autowired ISceneDataDownloadService sceneDataDownloadService; @Override public SceneEditInfoVO saveScene(SceneEditInfoParamVO param) { ScenePro scenePro = sceneProService.findBySceneNum(param.getNum()); if(Objects.isNull(scenePro)){ throw new BusinessException(ErrorCode.FAILURE_CODE_5005); } SceneEditInfo sceneEditInfoDb = this.getBySceneProId(scenePro.getId()); SceneEditControls sceneEditControlsDb = null; if(Objects.nonNull(sceneEditInfoDb)){ sceneEditControlsDb = sceneEditControlsService.getBySceneEditId(sceneEditInfoDb.getId()); } SceneEditInfo sceneEditInfo = BeanUtil.copyProperties(param, SceneEditInfo.class); sceneEditInfo.setSceneProId(scenePro.getId()); sceneEditInfo.setCreateTime(Calendar.getInstance().getTime()); if(Objects.isNull(sceneEditInfoDb)){ this.save(sceneEditInfo); }else{ sceneEditInfo.setId(sceneEditInfoDb.getId()); sceneEditInfo.setUpdateTime(Calendar.getInstance().getTime()); this.updateById(sceneEditInfo); } if(Objects.nonNull(param.getControls())){ SceneEditControls sceneEditControls = BeanUtil.copyProperties(param.getControls(), SceneEditControls.class); sceneEditControls.setEditInfoId(sceneEditInfo.getId()); if(Objects.isNull(sceneEditControlsDb)){ sceneEditControlsService.save(sceneEditControls); }else{ sceneEditControls.setId(sceneEditControlsDb.getId()); sceneEditControlsService.updateById(sceneEditControls); } } SceneEditInfoVO result = BeanUtil.copyProperties(param, SceneEditInfoVO.class); result.setCreateTime(sceneEditInfo.getCreateTime()); return result; } @Override public SceneEditInfo getBySceneProId(long sceneProId) { return this.getOne(new LambdaQueryWrapper() .eq(SceneEditInfo::getTbStatus, TbStatus.VALID.code()) .eq(SceneEditInfo::getSceneProId, sceneProId)); } @Override public ResultData publicScene(SceneEditInfoParamVO param) throws Exception{ String sceneNum = param.getNum(); if(StrUtil.isEmpty(sceneNum)){ throw new BusinessException(ErrorCode.PARAM_REQUIRED); } //根据场景码查询数据库 ScenePro scenePro = sceneProService.findBySceneNum(sceneNum); SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId()); SceneEditInfo sceneEditInfo = this.getBySceneProId(scenePro.getId()); SceneEditControls sceneEditControls = null; if(sceneEditInfo == null){ sceneEditInfo = new SceneEditInfo(); sceneEditInfo.setSceneProId(scenePro.getId()); }else{ sceneEditControls = sceneEditControlsService.getBySceneEditId(sceneEditInfo.getId()); } // if(sceneEditControls == null){ // sceneEditControls = new SceneEditControls(); // } //生成sceneJson SceneJsonBean sceneJson = BeanUtil.copyProperties(sceneEditInfo, SceneJsonBean.class); SceneEditControlsVO sceneEditControlsVO = BeanUtil.copyProperties(sceneEditControls, SceneEditControlsVO.class); sceneJson.setControls(sceneEditControlsVO); sceneJson.setNum(sceneNum); if(StrUtil.isNotEmpty(sceneEditInfo.getFloorPlanPath())){ sceneJson.setFloorPlanPaths(sceneEditInfo.getFloorPlanPath().split(",")); } sceneJson.setCreateTime(scenePro.getCreateTime()); //处理热点数据,生成hot.json this.publicHotData(sceneNum, sceneJson, sceneEditInfo); //处理球幕视频 this.buildVideo(sceneEditInfo, sceneProExt.getDataSource(), sceneNum); //上传sceneJson文件 String sceneJsonPath = String.format(UploadFilePath.DATA_VIEW_PATH+"scene.json", sceneNum); uploadToOssUtil.upload(JSON.toJSONBytes(sceneJson), sceneJsonPath); //sceneJson放入缓存 String key = String.format(RedisKey.SCENE_JSON, sceneNum); redisUtil.set(key, JSON.toJSONString(sceneJson)); //删除发布数据中的user目录 String publicUserPath = String.format(UploadFilePath.USER_VIEW_PATH, sceneNum); uploadToOssUtil.deleteFile(publicUserPath); // String editUserPath = String.format(UploadFilePath.USER_EDIT_PATH, sceneNum); //复制编辑目录到发布目录 String editPath = String.format(UploadFilePath.EDIT_PATH, param.getNum()); String viewPath = String.format(UploadFilePath.VIEW_PATH, param.getNum()); uploadToOssUtil.copyFiles(editPath,viewPath); //入库 if(sceneEditInfo.getId() == null){ this.save(sceneEditInfo); }else{ this.updateById(sceneEditInfo); } // sceneEditControls.setEditInfoId(sceneEditInfo.getId()); // if(sceneEditControls.getId() == null){ // sceneEditControlsService.save(sceneEditControls); // }else{ // sceneEditControlsService.updateById(sceneEditControls); // } return ResultData.ok(); } private void buildVideo(SceneEditInfo sceneEditInfo, String path, String num) throws Exception{ if(CommonStatus.NO.equals(sceneEditInfo.getBuildVideoStatus())){ return; } if(path != null && !"".equals(path) && path.startsWith("http")){ path = ConstantFilePath.BUILD_MODEL_PATH + File.separator + path.split("/")[path.split("/").length - 2]; } String target = path + "_images"; log.info("球幕视频路径:{}", target + File.separator + "extras/video"); File video = new File(target + File.separator + "extras/video"); //如果文件夹或者文件不存在,跳出 if(!video.exists() || video.listFiles() == null || video.listFiles().length == 0){ return; } String userEditPath = String.format(UploadFilePath.USER_EDIT_PATH, num); for(String videoName : video.list()){ log.info("球幕视频名称:{}", videoName); uploadToOssUtil.upload(target + File.separator + "extras/video/" + videoName,userEditPath + videoName); CreateObjUtil.mp4ToFlv(target + File.separator + "extras/video/" + videoName, target + File.separator + "extras/video/" + videoName.replace("mp4", "flv")); uploadToOssUtil.upload(target + File.separator + "extras/video/" + videoName.replace("mp4", "flv"),userEditPath + videoName.replace("mp4", "flv")); //覆盖原始视频资源 FileUtils.copyFile(target + File.separator + "extras/video/" + videoName, path + File.separator + "caches/videos/" + videoName, true); } FileUtils.deleteDirectory(target + File.separator + "extras/video/"); //重置状态 sceneEditInfo.setBuildVideoStatus(CommonStatus.NO.code()); } private void publicHotData(String sceneNum, SceneJsonBean sceneJson, SceneEditInfo sceneEditInfo) throws IOException { String hotDataKey = String.format(RedisKey.SCENE_HOT_DATA, sceneNum); Map hotMap = redisUtil.hmget(hotDataKey); List hotList = Lists.newArrayList(); hotMap.entrySet().stream().forEach(entry->{ if(StrUtil.isNotEmpty(entry.getValue())){ hotList.add(entry.getValue()); } }); if(CollUtil.isNotEmpty(hotList)){ JSONArray jsonhots = new JSONArray(); hotList.stream().forEach(hot->{ jsonhots.add(JSONObject.parseObject(hot)); }); String hotJsonPath = String.format(UploadFilePath.USER_EDIT_PATH, sceneNum) + "hot.json"; uploadToOssUtil.upload(jsonhots.toString().getBytes(), hotJsonPath); //修改tags状态为是,标识有热点数据 ScenePro scenePro = sceneProService.findBySceneNum(sceneNum); this.saveTagsToSceneEditInfo(sceneNum, scenePro.getId(), sceneEditInfo); } } @Override public SceneInfoVO getSceneInfo(@Var SceneInfoParamVO param) { SceneInfoReqType sceneInfoReqType = SceneInfoReqType.get(param.getReqType()); switch (sceneInfoReqType){ //如果是编辑页面请求,查数据库 case EDIT: return this.getSceneInfo4Edit(param.getNum()); //如果是查看页面请求,查redis case VIEW: return this.getSceneInfo4View(param.getNum()); } return null; } /** *

编辑页面获取场景详情信息 *

* @author dengsixing * @date 2022/1/21 * @param num * @return com.fdkankan.scene.vo.SceneInfoVO **/ private SceneInfoVO getSceneInfo4Edit(String num){ ScenePro scenePro = sceneProService.findBySceneNum(num); if(Objects.isNull(scenePro)){ throw new BusinessException(ErrorCode.FAILURE_CODE_5005); } SceneEditInfo sceneEditInfo = this.getBySceneProId(scenePro.getId()); SceneEditControls sceneEditControls = sceneEditControlsService.getBySceneEditId(sceneEditInfo.getId()); SceneInfoVO sceneInfoVO = BeanUtil.copyProperties(sceneEditInfo, SceneInfoVO.class); sceneInfoVO.setControls(BeanUtil.copyProperties(sceneEditControls, SceneEditControlsVO.class)); sceneInfoVO.setNum(num); //生成sceneJson if(StrUtil.isNotEmpty(sceneEditInfo.getFloorPlanPath())){ sceneInfoVO.setFloorPlanPaths(sceneEditInfo.getFloorPlanPath().split(",")); } sceneInfoVO.setCreateTime(scenePro.getCreateTime()); return sceneInfoVO; } /** *

查看页面获取场景详情信息 *

* @author dengsixing * @date 2022/1/21 * @param num * @return com.fdkankan.scene.vo.SceneInfoVO **/ private SceneInfoVO getSceneInfo4View(String num){ String sceneJson = redisUtil.get(String.format(RedisKey.SCENE_JSON, num)); SceneInfoVO sceneInfoVO = null; //先查询redis if(StrUtil.isNotEmpty(sceneJson)){ sceneInfoVO = JSON.parseObject(sceneJson, SceneInfoVO.class); return sceneInfoVO; } //如果redis没找到,从scene.json中获取 String objectName = String.format(ConstantFilePath.SCENE_VIEW_DATA_DATA_SCENEJSON, num); String objectContent = uploadToOssUtil.getObjectContent(bucket, objectName); if(StrUtil.isEmpty(objectContent)) return null; sceneInfoVO = JSON.parseObject(objectContent, SceneInfoVO.class); return sceneInfoVO; } @Override // @Transactional public ResultData saveUpload(SaveUploadParamVO param) throws Exception { FileBizType fileBizType = FileBizType.get(param.getBizType()); String num = param.getNum(); String fileInfo = param.getFileInfo(); if(Objects.isNull(fileBizType)){ throw new BusinessException(ErrorCode.FAILURE_CODE_7003); } switch (fileBizType){ case MUSIC: return new MusicHandlerFactory().getHandler().save(num, fileInfo); case FLOOR_LOGO: return new FloorLogoHandlerFactory().getHandler().save(num, fileInfo); // case FLOOR_PLAN: // return new FloorPlanHandlerFactory().getHandler().save(num, fileInfo); case SCREENSHOT: return new ScreenshotHandlerFactory().getHandler().save(num, fileInfo); } return ResultData.ok(); } @Override public ResultData saveCad(BaseDataParamVO param) throws Exception { String num = param.getNum(); ScenePro scenePro = sceneProService.findBySceneNum(num); if(Objects.isNull(scenePro)) throw new BusinessException(ErrorCode.FAILURE_CODE_5005); String editDataPath = String.format(UploadFilePath.DATA_EDIT_PATH, num); String editUserPath = String.format(UploadFilePath.USER_EDIT_PATH, num); String localDataPath = String.format(ConstantFilePath.DATABUFFER_FORMAT, num); String floorCadUrl = ossUrlPrefix + editDataPath + "floorplan_cad.json?t=" + System.currentTimeMillis(); String floorUserUrl = ossUrlPrefix + editUserPath + "floorplan_user.json?t=" + System.currentTimeMillis(); JSONObject fileInfoJson = JSON.parseObject(param.getData()); String filePathStr = null; String floors = fileInfoJson.getString("floors"); String cadInfo = fileInfoJson.getString("cadInfo"); String floorJsonData = fileInfoJson.getString("floorJsonData"); String filePaths = fileInfoJson.getString("filePaths"); // Byte reSet = fileInfoJson.getByte("reset"); //户型图文件路径 if(StrUtil.isNotEmpty(filePaths)){ cn.hutool.json.JSONArray filePathsArrs = JSONUtil.parseArray(filePaths); List filePathsList = filePathsArrs.toList(String.class); StringBuilder filePathBuilder = new StringBuilder(); filePathsList.parallelStream().forEach(path -> { filePathBuilder.append(",").append(path); }); filePathStr = filePathBuilder.substring(1); } //处理户型图数据 if(StrUtil.isNotEmpty(floors)) { //如果入参是空,则加载服务器的 if(StrUtil.isEmpty(floorJsonData)){ if (!StorageType.LOCAL.code().equals(this.type)) {// TODO: 2022/2/15 这里有可能有问题,可能还需要考虑本地部署的情况 FileUtils.downLoadFromUrl(floorUserUrl, "floorplan_user.json", localDataPath); } floorJsonData = FileUtils.readFile(localDataPath + "floorplan_user.json"); } //如果floors不为空,需要根据对应楼层id修改楼层名称 if (StrUtil.isNotEmpty(floorJsonData)) { JSONObject floorUserJson = this.updateFloorName(floors, floorJsonData); floorJsonData = floorUserJson.toJSONString(); } } //上传floorplan_user.json文件 FileUtils.writeFile(localDataPath + "floorplan_user.json", floorJsonData); uploadToOssUtil.upload(localDataPath + "floorplan_user.json", editUserPath + "floorplan_user.json"); //如果floors不为空,需要根据对应楼层id修改楼层名称 if(StrUtil.isNotEmpty(floors)) { if (!StorageType.LOCAL.code().equals(this.type)) {// TODO: 2022/2/15 这里有可能有问题,可能还需要考虑本地部署的情况 FileUtils.downLoadFromUrl(floorCadUrl, "floorplan_cad.json", localDataPath); } String floorCadStr = FileUtils.readFile(localDataPath + "floorplan_cad.json"); if (StrUtil.isNotEmpty(floorCadStr)) { JSONObject floorCadJson = this.updateFloorName(floors, floorCadStr); FileUtils.writeFile(localDataPath + "floorplan_cad.json", floorCadJson.toString()); uploadToOssUtil.upload(localDataPath + "floorplan_cad.json",editDataPath + "floorplan_cad.json"); } } //写入数据库 Byte floorPlanUser = null; if(StrUtil.isNotEmpty(floorJsonData)){ floorPlanUser = CommonStatus.YES.code(); } // if(CommonStatus.YES.code().equals(reSet)){ // floorPlanUser = CommonStatus.NO.code(); // } SceneEditInfo sceneEditInfoDb = this.getBySceneProId(scenePro.getId()); if(Objects.nonNull(sceneEditInfoDb)){ LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper() .setSql("version=version+" + 1) .eq(SceneEditInfo::getId, sceneEditInfoDb.getId()); if(StrUtil.isNotEmpty(filePathStr)){ updateWrapper.set(SceneEditInfo::getFloorPlanPath, filePathStr); } if(StrUtil.isNotEmpty(cadInfo)){ updateWrapper.set(SceneEditInfo::getCadInfo, cadInfo); } if(floorPlanUser != null){ updateWrapper.set(SceneEditInfo::getFloorPlanUser, floorPlanUser); } this.update(updateWrapper); }else{ sceneEditInfoDb = new SceneEditInfo(); sceneEditInfoDb.setSceneProId(scenePro.getId()); sceneEditInfoDb.setFloorPlanPath(filePathStr); sceneEditInfoDb.setCadInfo(cadInfo); sceneEditInfoDb.setFloorPlanUser(floorPlanUser); this.save(sceneEditInfoDb); } return ResultData.ok(); } @Override public ResultData resetCad(String num){ ScenePro scenePro = sceneProService.findBySceneNum(num); if(Objects.isNull(scenePro)) throw new BusinessException(ErrorCode.FAILURE_CODE_5005); SceneEditInfo sceneEditInfoDb = this.getBySceneProId(scenePro.getId()); if(Objects.nonNull(sceneEditInfoDb)){ LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper() .setSql("version=version+" + 1) .set(SceneEditInfo::getFloorPlanUser, CommonStatus.NO.code()) .eq(SceneEditInfo::getId, sceneEditInfoDb.getId()); this.update(updateWrapper); }else{ sceneEditInfoDb = new SceneEditInfo(); sceneEditInfoDb.setSceneProId(scenePro.getId()); sceneEditInfoDb.setFloorPlanUser(CommonStatus.NO.code()); this.save(sceneEditInfoDb); } return ResultData.ok(); } private JSONObject updateFloorName(String sourceFloors, String targeFloors){ JSONArray sourceFloorsJson = JSON.parseArray(sourceFloors); JSONObject targeFloorsJson = JSONObject.parseObject(targeFloors); JSONArray array = targeFloorsJson.getJSONArray("floors"); for (int i = 0; i < array.size(); ++i) { JSONObject targetFloor = array.getJSONObject(i); int targetId = targetFloor.getIntValue("id"); for (int j = 0; j < sourceFloorsJson.size(); ++j) { JSONObject floor = sourceFloorsJson.getJSONObject(j); int id = floor.getIntValue("id"); String name = floor.getString("name"); if (targetId != id) continue; targetFloor.put("name", name); } } return targeFloorsJson; } @Override public void upgradeVersionById(Long id) { this.update(new LambdaUpdateWrapper() .setSql("version=version+" + 1) .eq(SceneEditInfo::getId, id)); } @Override public List uploadPanorama(String num, MultipartFile file) throws Exception { //压缩包保存到本地 String path = String.format(ConstantFilePath.SCENE_CACHE_IMAGES, num); // String path = "F:\\mnt\\4Dkankan\\scene\\t-ieXdyGl6Md\\caches\\images\\"; String targetFilePath = path + File.separator + file.getOriginalFilename(); File targetFile = new File(targetFilePath); if(!targetFile.getParentFile().exists()){ targetFile.getParentFile().mkdirs(); } file.transferTo(targetFile); //解压zip包 FileUtil.unZip(targetFilePath, path); //删除压缩包 FileUtil.delFile(targetFilePath); //获取解压后的文件列表 List uploadFileList = FileUtil.getFileList(path); if(CollUtil.isEmpty(uploadFileList)){ return null; } //列出caches/images中的文件列表 String imgCachePath = String.format(UploadFilePath.IMG_CACHES_PATH, num); List keyList = uploadToOssUtil.listKeys(imgCachePath); //比对图片列表,不存在的要返回名称集合 List notExistFileList = uploadFileList.stream().filter(filePath -> { filePath = filePath.substring(filePath.lastIndexOf(File.separator) + 1); for (String key : keyList) { key = key.substring(key.lastIndexOf("/") + 1); if (filePath.equals(key)) { return false; } } return true; }).map(filePath -> { return filePath.substring(filePath.lastIndexOf(File.separator) + 1); }).collect(Collectors.toList()); //删除云caches/images uploadToOssUtil.deleteFile(imgCachePath); //上传 Map map = new HashMap<>(); uploadFileList.stream().forEach(filePath->{ map.put(filePath, filePath.replace(path, imgCachePath)); }); uploadToOssUtil.uploadMulFiles(map); return notExistFileList; } @Override public ResultData downloadPanorama(FileParamVO param) throws Exception { String num = param.getNum(); String fileName = param.getFileName(); String cachePath = String.format(ConstantFilePath.SCENE_CACHE, num); String imgCachePath = String.format(UploadFilePath.IMG_CACHES_PATH, num); String localImagesPath = String.format(ConstantFilePath.SCENE_CACHE_IMAGES, num); String cacheFormat = "downloads/scene/%s/caches/"; String cacheImageFormat = "downloads/scene/%s/caches/images/"; //删除本地文件 FileUtils.deleteDirectory(localImagesPath); //如果入参文件名不为空,则是单个文件下载,不需要打包 if(StrUtil.isNotEmpty(fileName)){ //先下载到本地 if (!StorageType.LOCAL.code().equals(this.type)) {// TODO: 2022/2/15 这里有可能有问题,可能还需要考虑本地部署的情况 String filePath = imgCachePath + fileName; String imageUrl = ossUrlPrefix + filePath + "?t=" + System.currentTimeMillis(); FileUtils.downLoadFromUrl(imageUrl, fileName, localImagesPath); } //上传 uploadToOssUtil.upload(localImagesPath + fileName, String.format(cacheImageFormat, num) + fileName); String url = ossUrlPrefix + String.format(cacheImageFormat, num) + fileName + "?t=" + Calendar.getInstance().getTimeInMillis(); Map map = new HashMap<>(); map.put("fileUrl", url + "?t=" + System.currentTimeMillis()); map.put("fileName", fileName); return ResultData.ok(map); } //先下载到本地 List keyList = uploadToOssUtil.listKeys(imgCachePath); if (!StorageType.LOCAL.code().equals(this.type)) {// TODO: 2022/2/15 这里有可能有问题,可能还需要考虑本地部署的情况 keyList.stream().forEach(key->{ String file = key.substring(key.lastIndexOf("/") + 1); String imageUrl = ossUrlPrefix + imgCachePath + file + "?t=" + System.currentTimeMillis(); FileUtils.downLoadFromUrl(imageUrl, file, localImagesPath); }); } //打包 String zipName = num + "_images.zip"; String zipPath = cachePath + zipName; FileUtils.zipFile(zipPath, localImagesPath); //上传压缩包 uploadToOssUtil.upload(zipPath, String.format(cacheFormat, num) + zipName); String url = ossUrlPrefix + String.format(cacheFormat, num) + zipName + "?t=" + Calendar.getInstance().getTimeInMillis(); Map map = new HashMap<>(); map.put("fileUrl", url + "?t=" + System.currentTimeMillis()); map.put("fileName", zipName); return ResultData.ok(map); } @Override public void saveTagsToSceneEditInfo(String num, Long sceneProId, SceneEditInfo sceneEditInfo){ //查询缓存是否包含热点数据 String key = String.format(RedisKey.SCENE_HOT_DATA, num); Map allTagsMap = redisUtil.hmget(key); boolean hashTags = false; for (Entry tagMap : allTagsMap.entrySet()) { if(StrUtil.isEmpty(tagMap.getValue())){ continue; } hashTags = true; break; } //更改热点状态 sceneEditInfo.setTags(hashTags ? CommonStatus.YES.code() : CommonStatus.NO.code()); //version 是空的代表 sceneEditInfo记录集不存在 if(sceneEditInfo.getVersion() != null){ sceneEditInfo.setVersion(sceneEditInfo.getVersion() + 1); } } @Override public ResultData saveVideoBox(FileNameAndDataParamVO param) throws Exception { JSONObject boxVideo = JSONObject.parseObject(param.getData()); String sid = boxVideo.getString("sid"); if(StrUtil.isEmpty(sid)){ throw new BusinessException(ErrorCode.PARAM_REQUIRED); } ScenePro scenePro = sceneProService.findBySceneNum(param.getNum()); if(Objects.isNull(scenePro)) throw new BusinessException(ErrorCode.FAILURE_CODE_5005); SceneEditInfo sceneEditInfo = this.getBySceneProId(scenePro.getId()); //转换视频格式 this.transferToFlv(param.getNum(), param.getFileName()); //生成boxVideos数据 String boxVideos = this.createBoxVideos(sid, boxVideo, sceneEditInfo, OperationType.ADDORUPDATE.code()); //更新数据库 this.updateBoxVideos(sceneEditInfo, scenePro.getId(), boxVideos); return ResultData.ok(); } @Override public ResultData deleteVideoBox(DeleteVidoeBoxParamVO param) throws Exception { ScenePro scenePro = sceneProService.findBySceneNum(param.getNum()); if(Objects.isNull(scenePro)) throw new BusinessException(ErrorCode.FAILURE_CODE_5005); SceneEditInfo sceneEditInfo = this.getBySceneProId(scenePro.getId()); //根据sid移除json String boxVideos = this.createBoxVideos(param.getSid(), null, sceneEditInfo, OperationType.DELETE.code()); //写数据库 this.updateBoxVideos(sceneEditInfo,scenePro.getId(),boxVideos); return ResultData.ok(); } @Override public DownloadVO downloadBallScreenVideo(BallScreenVideoParamVO param) { String videoPath = String.format(UploadFilePath.USER_EDIT_PATH, param.getNum()) + param.getFileName(); String url = ossUrlPrefix + videoPath + "?t=" + System.currentTimeMillis(); return DownloadVO.builder() .fileName(param.getFileName()) .url(url) .build(); } @Override public ResultData uploadBallScreenVideo(String num, String fileName, MultipartFile file) throws IOException { if(!fileName.endsWith(".mp4")){ throw new BusinessException(ErrorCode.FAILURE_CODE_7007.code(), ErrorCode.FAILURE_CODE_7007.formatMessage("mp4")); } ScenePro scenePro = sceneProService.findBySceneNum(num); if(scenePro == null){ throw new BusinessException(ErrorCode.FAILURE_CODE_5005); } SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId()); String path = sceneProExt.getDataSource(); if(path != null && !"".equals(path) && path.startsWith("http")){ path = ConstantFilePath.BUILD_MODEL_PATH + File.separator + path.split("/")[path.split("/").length - 2]; } String target = path + "_images"; String filePath = target + File.separator + "extras/video" + File.separator + fileName; File targetFile = new File(filePath); if(!targetFile.getParentFile().exists()){ targetFile.getParentFile().mkdirs(); } //保存视频到本地 file.transferTo(targetFile); SceneEditInfo sceneEditInfo = this.getBySceneProId(scenePro.getId()); if(sceneEditInfo == null){ sceneEditInfo = new SceneEditInfo(); sceneEditInfo.setSceneProId(scenePro.getId()); sceneEditInfo.setBuildVideoStatus(CommonStatus.YES.code()); this.save(sceneEditInfo); }else{ sceneEditInfo.setBuildVideoStatus(CommonStatus.YES.code()); this.updateById(sceneEditInfo); } return ResultData.ok(); } @Override public ResultData sceneSync(String num, String type, String floorPlanJson, String ajkJson, String cameraJson, MultipartFile[] files) throws Exception { String lockKey = String.format(RedisLockKey.LOCK_SCENE_SYNC, num); Boolean lock = redisLockUtil.lock(lockKey, RedisKey.EXPIRE_TIME_2_HOUR); if(!lock){ throw new BusinessException(ErrorCode.FAILURE_CODE_5036); } try { ScenePro scenePro = sceneProService.findBySceneNum(num); if(scenePro == null){ throw new BusinessException(ErrorCode.FAILURE_CODE_5005); } SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId()); //更新scene.json文件 String strsceneInfos = FileUtils.readFile(ConstantFilePath.SCENE_PATH + "data" + File.separator + "data" + num + File.separator + "scene.json"); if(strsceneInfos == null) new File(ConstantFilePath.SCENE_PATH + "data" + File.separator + "data" + num + File.separator + "scene.json").createNewFile(); String path = sceneProExt.getDataSource();// /mnt/data/0662c5389/831989883441512448/4898cab04f8c_202104141602356060/ if(path != null && !"".equals(path) && path.startsWith("http")){ path = ConstantFilePath.BUILD_MODEL_PATH + File.separator + path.split("/")[path.split("/").length - 2]; } String target = path + "_ajk"; // /mnt/data/0662c5389/831989883441512448/4898cab04f8c_202104141602356060_ajk File editPath = new File(target); if(!editPath.exists()){ editPath.mkdirs(); } //创建文件夹软连接并且复制data.json和project.json if(new File(target + File.separator + "capture").exists()){ new File(target + File.separator + "capture").delete(); } if(new File(target + File.separator + "caches").exists()){ //删除link new File(target + File.separator + "caches" + File.separator + "images").delete(); //删除所有文件 FileUtils.delAllFile(target + File.separator + "caches"); } if(new File(target + File.separator + "results").exists()){ FileUtils.delAllFile(target + File.separator + "results"); } //创建文件夹,并link文件夹 new File(target + File.separator + "caches").mkdirs(); CreateObjUtil.createSoftConnection(path + File.separator + "capture", target + File.separator + "capture"); if(new File(path + File.separator + "caches" + File.separator + "images").exists()){ CreateObjUtil.createSoftConnection(path + File.separator + "caches" + File.separator + "images", target + File.separator + "caches" + File.separator + "images"); } FileUtils.copyFile(path + File.separator + "data.json", target + File.separator+"data.json", true); FileUtils.copyFile(path + File.separator + "project.json", target + File.separator+"project.json", true); //data.json增加extras为执行重建算法 String project = FileUtils.readFile(target + File.separator+"project.json"); if(project != null){ JSONObject projectJson = JSONObject.parseObject(project); projectJson.put("parent", projectJson.get("uuid")); projectJson.put("uuid", UUID.randomUUID().toString()); projectJson.put("time", System.currentTimeMillis()); FileUtils.writeFile(path + File.separator + "project.json", projectJson.toString()); } String data = FileUtils.readFile(target + File.separator+"data.json"); if(data != null){ JSONObject floorplanJson = new JSONObject(); floorplanJson.put("has_floor_ajk_json", true); floorplanJson.put("has_vision_txt", true); floorplanJson.put("has_floorplan_json", true); JSONObject dataJson = JSONObject.parseObject(data); dataJson.put("extras", floorplanJson); //V5表示不需要生成high,low文件 dataJson.put("skybox_type", "SKYBOX_V8"); dataJson.put("split_type", "SPLIT_V10"); FileUtils.writeFile(target + File.separator+"data.json", new String(dataJson.toString().getBytes(), "UTF-8")); } //文件上传的位置可以自定义 log.info("画墙重建模型开始"); File targetFile = new File(target + File.separator + "extras" + File.separator + "floor_ajk.json"); if(!targetFile.getParentFile().exists()){ targetFile.getParentFile().mkdirs(); } if(targetFile.exists()){ FileUtils.deleteFile(target + File.separator + "extras" + File.separator + "floor_ajk.json"); } // 保存 FileUtils.writeFile(target + File.separator + "extras" + File.separator + "floorplan.json", new String(floorPlanJson.getBytes(), "UTF-8")); FileUtils.writeFile(target + File.separator + "extras" + File.separator + "floor_ajk.json", new String(ajkJson.getBytes(), "UTF-8")); FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+num + File.separator + "floor_ajk.json", new String(ajkJson.getBytes(), "UTF-8")); FileUtils.writeFile(target + File.separator + "extras" + File.separator + "vision.txt", new String(cameraJson.getBytes(), "UTF-8")); FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+num + File.separator + "camera.json", new String(cameraJson.getBytes(), "UTF-8")); for(int i = 0; i < files.length; i ++){ File cadImg = new File(target + File.separator + "extras" + File.separator + "Floorplans/" + files[i].getOriginalFilename()); if(!cadImg.getParentFile().exists()){ cadImg.getParentFile().mkdirs(); } if(cadImg.exists()) { cadImg.delete(); } files[i].transferTo(cadImg); } //下载封面图 FileUtils.downLoadFromUrl(scenePro.getThumb() + "?t=" + System.currentTimeMillis(), "Cover.png", target + File.separator + "extras" + File.separator + "CoverImage"); //转换成jpg FileUtils.pngToJpg(target + File.separator + "extras" + File.separator + "CoverImage/Cover.png", target + File.separator + "extras" + File.separator + "CoverImage/Cover.jpg"); //安居客算法运行 log.info("安居客算法:开始建模——"+num); CreateObjUtil.build3dModel(target , "1"); if(!new File(target + File.separator + "results" + File.separator + "upload.json").exists()){ return ResultData.error(ErrorCode.FAILURE_CODE_5042); } String zipPath = target + File.separator + "results/" + num + ".zip"; new File(zipPath).delete(); // FileUtils.zipFile(zipPath, target + File.separator + "results/ajk/"); String command = "bash /opt/ossutil/gzip.sh " + zipPath.replace(".zip", "") + " " + target + File.separator + "results/ajk/"; log.info("压缩文件:" + command); CreateObjUtil.callshell(command); if(!new File(zipPath).exists()){ return ResultData.error(ErrorCode.FAILURE_CODE_5043); } String fileMD5 = FileMd5Util.getFileMD5(new File(zipPath)); uploadToOssUtil.upload(zipPath, "data_download/" + num + ".zip"); SceneDataDownload sceneDataDownload = sceneDataDownloadService.findBySceneNum(num); if(sceneDataDownload == null){ sceneDataDownload = new SceneDataDownload(); sceneDataDownload.setNum(num); sceneDataDownload.setDownloadPath(prefixAli + "data_download/" + num + ".zip"); sceneDataDownload.setFileMd5(fileMD5); sceneDataDownloadService.save(sceneDataDownload); return ResultData.ok(); } sceneDataDownload.setFileMd5(fileMD5); sceneDataDownload.setUpdateTime(Calendar.getInstance().getTime()); sceneDataDownloadService.updateById(sceneDataDownload); }catch (Exception e){ log.error("画墙重建模型失败...", e); throw new BusinessException(ErrorCode.FAILURE_CODE_5039); }finally { redisLockUtil.unlockLua(lockKey); } return ResultData.ok(); } private void updateBoxVideos(SceneEditInfo sceneEditInfo, Long sceneProId, String boxVideos){ if(StrUtil.isEmpty(boxVideos)){ return; } if(Objects.isNull(sceneEditInfo)){ sceneEditInfo = new SceneEditInfo(); sceneEditInfo.setSceneProId(sceneProId); sceneEditInfo.setBoxVideos(boxVideos); this.save(sceneEditInfo); }else{ this.update(new LambdaUpdateWrapper() .setSql("version = version + 1") .set(SceneEditInfo::getBoxVideos, boxVideos) .eq(SceneEditInfo::getId, sceneEditInfo.getId())); } } private String createBoxVideos(String sid, JSONObject boxVideo, SceneEditInfo sceneEditInfo, int type){ String boxVideos = null; if(sceneEditInfo != null){ boxVideos = sceneEditInfo.getBoxVideos(); } JSONArray boxVideosJson = null; if (StrUtil.isNotEmpty(boxVideos)) { boxVideosJson = JSONArray.parseArray(boxVideos); }else { boxVideosJson = new JSONArray(); } //删除 if(type == OperationType.DELETE.code()){ if(boxVideosJson.size() == 0) return null; for(int i=0;i