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.core.util.ZipUtil; 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.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.fdkankan.common.constant.CommonStatus; import com.fdkankan.model.constants.ConstantFilePath; import com.fdkankan.common.constant.ErrorCode; import com.fdkankan.common.constant.FileBizType; import com.fdkankan.common.constant.OperationType; import com.fdkankan.common.constant.SceneFrom; import com.fdkankan.common.constant.SceneInfoReqType; import com.fdkankan.common.constant.ServerCode; import com.fdkankan.model.constants.UploadFilePath; import com.fdkankan.common.exception.BusinessException; import com.fdkankan.common.response.ResultData; import com.fdkankan.model.utils.ComputerUtil; import com.fdkankan.model.utils.CreateHouseJsonUtil; import com.fdkankan.model.utils.CreateObjUtil; import com.fdkankan.common.util.FileMd5Util; import com.fdkankan.common.util.FileUtil; import com.fdkankan.common.util.FileUtils; import com.fdkankan.model.utils.SceneUtil; import com.fdkankan.fyun.constant.FYunTypeEnum; import com.fdkankan.fyun.face.FYunFileServiceInterface; 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.BoxPhotoBean; import com.fdkankan.scene.bean.PointBean; 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.entity.CameraDetail; import com.fdkankan.scene.entity.Company; import com.fdkankan.scene.entity.SceneDataDownload; import com.fdkankan.scene.entity.SceneEditControls; import com.fdkankan.scene.entity.SceneEditInfo; import com.fdkankan.scene.entity.SceneEditInfoExt; import com.fdkankan.scene.entity.ScenePlus; 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.ISceneDataDownloadService; import com.fdkankan.scene.service.ISceneEditControlsService; import com.fdkankan.scene.service.ISceneEditInfoExtService; import com.fdkankan.scene.service.ISceneEditInfoService; import com.fdkankan.scene.service.IScenePlusExtService; import com.fdkankan.scene.service.IScenePlusService; import com.fdkankan.scene.service.ISceneProService; import com.fdkankan.scene.service.ISceneUploadService; import com.fdkankan.scene.vo.BallScreenVideoParamVO; import com.fdkankan.scene.vo.BaseDataParamVO; import com.fdkankan.scene.vo.BaseFileParamVO; import com.fdkankan.scene.vo.DeleteFileParamVO; import com.fdkankan.scene.vo.DeleteLinkPanParamVO; import com.fdkankan.scene.vo.DeleteLinkSceneStylesParamVO; import com.fdkankan.scene.vo.DeleteMosaicParamVO; import com.fdkankan.scene.vo.DeleteSidParamVO; import com.fdkankan.scene.vo.DownloadVO; import com.fdkankan.scene.vo.FileNameAndDataParamVO; import com.fdkankan.scene.vo.FileParamVO; import com.fdkankan.scene.vo.RenameCadParamVO; import com.fdkankan.scene.vo.SaveLinkPanParamVO; import com.fdkankan.scene.vo.SceneCheckKeyParamVO; import com.fdkankan.scene.vo.SceneEditControlsVO; import com.fdkankan.scene.vo.SceneEditInfoParamVO; import com.fdkankan.scene.vo.SceneEditInfoVO; import com.fdkankan.scene.vo.SceneInfoParamVO; import com.fdkankan.scene.vo.SceneInfoVO; import com.fdkankan.scene.vo.UploadPanoramaVO; import com.google.common.collect.Lists; import com.google.errorprone.annotations.Var; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Set; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; 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.cloud.context.config.annotation.RefreshScope; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; /** *
* 服务实现类 *
* * @author * @since 2022-01-18 */ @Slf4j @RefreshScope @Service public class SceneEditInfoServiceImpl extends ServiceImpl编辑页面获取场景详情信息 *
* @author dengsixing * @date 2022/1/21 * @param num * @return com.fdkankan.scene.vo.SceneInfoVO **/ private SceneInfoVO getSceneInfo4Edit(String num) throws Exception{ ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num); if(Objects.isNull(scenePlus)){ throw new BusinessException(ErrorCode.FAILURE_CODE_5005); } ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId()); SceneEditInfo sceneEditInfo = this.getByScenePlusId(scenePlus.getId()); if(Objects.isNull(sceneEditInfo)){ throw new BusinessException(ErrorCode.FAILURE_CODE_5005); } SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByEditInfoId(sceneEditInfo.getId()); SceneEditControls sceneEditControls = sceneEditControlsService.getBySceneEditId(sceneEditInfo.getId()); SceneInfoVO sceneInfoVO = new SceneInfoVO(); BeanUtil.copyProperties(sceneEditInfoExt, sceneInfoVO); BeanUtil.copyProperties(sceneEditInfo, sceneInfoVO); if(Objects.isNull(sceneInfoVO.getFloorPlanAngle())){ sceneInfoVO.setFloorPlanAngle(0f); } if(Objects.isNull(sceneInfoVO.getFloorPlanCompass())){ sceneInfoVO.setFloorPlanCompass(0f); } sceneInfoVO.setControls(BeanUtil.copyProperties(sceneEditControls, SceneEditControlsVO.class)); sceneInfoVO.setNum(num); sceneInfoVO.setCreateTime(scenePlus.getCreateTime()); sceneInfoVO.setSceneResolution(scenePlusExt.getSceneResolution()); sceneInfoVO.setSceneFrom(scenePlusExt.getSceneFrom()); sceneInfoVO.setSceneKind(scenePlusExt.getSceneKind()); sceneInfoVO.setVideos(scenePlusExt.getVideos()); sceneInfoVO.setMosaicList(this.getMosaicList(num)); this.setExtData(sceneInfoVO, scenePlus.getCameraId()); return sceneInfoVO; } /** *getInfo接口返回字段扩展 *
* @author dengsixing * @date 2022/3/9 **/ private void setExtData(SceneInfoVO sceneInfoVO, Long cameraId) throws Exception{ if(Objects.isNull(cameraId)){ return; } CameraDetail cameraDetail = cameraDetailService.findByCameraId(cameraId); if(Objects.isNull(cameraDetail)){ throw new BusinessException(ErrorCode.FAILURE_CODE_7010); } if(Objects.isNull(cameraDetail.getCompanyId())){ return; } Company company = companyService.getById(cameraDetail.getCompanyId()); if(Objects.isNull(company)){ return; } sceneInfoVO.setDataSync(company.getDataSync()); } /** *查看页面获取场景详情信息 *
* @author dengsixing * @date 2022/1/21 * @param num * @return com.fdkankan.scene.vo.SceneInfoVO **/ private SceneInfoVO getSceneInfo4View(String num) throws Exception{ //校验场景是否为空、封存、计算中 ScenePlus scenePlus = scenePlusService.checkSceneAvail(num); ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId()); //访问量+1 scenePlusService.updateViewCount(num); String key = String.format(RedisKey.SCENE_JSON, num); String sceneJson = redisUtil.get(key); SceneInfoVO sceneInfoVO = null; //先查询redis if(StrUtil.isNotEmpty(sceneJson)) { sceneInfoVO = JSON.parseObject(sceneJson, SceneInfoVO.class); sceneInfoVO.setScenePassword(null); if(Objects.isNull(sceneInfoVO.getFloorPlanAngle())){ sceneInfoVO.setFloorPlanAngle(0f); } if(Objects.isNull(sceneInfoVO.getFloorPlanCompass())){ sceneInfoVO.setFloorPlanCompass(0f); } return sceneInfoVO; } //如果redis没找到,从scene.json中获取 String objectName = String.format(ConstantFilePath.SCENE_VIEW_DATA_DATA_SCENEJSON, num); String objectContent = fYunFileService.getFileContent(scenePlusExt.getYunFileBucket(), objectName); if(StrUtil.isEmpty(objectContent)) return null; sceneInfoVO = JSON.parseObject(objectContent, SceneInfoVO.class); if(Objects.isNull(sceneInfoVO.getFloorPlanAngle())){ sceneInfoVO.setFloorPlanAngle(0f); } if(Objects.isNull(sceneInfoVO.getFloorPlanCompass())){ sceneInfoVO.setFloorPlanCompass(0f); } redisUtil.set(key, JSON.toJSONString(sceneInfoVO)); sceneInfoVO.setScenePassword(null); return sceneInfoVO; } @Override public ResultData saveCad(BaseDataParamVO param) throws Exception { String num = param.getNum(); ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num); if(Objects.isNull(scenePlus)) throw new BusinessException(ErrorCode.FAILURE_CODE_5005); ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId()); String bucket = scenePlusExt.getYunFileBucket(); String editUserPath = String.format(UploadFilePath.USER_EDIT_PATH, num); String localDataPath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num); JSONObject fileInfoJson = JSON.parseObject(param.getData()); Float angel = null; Float compass = null; String floorJsonData = fileInfoJson.getString("floorJsonData"); if(StrUtil.isNotBlank(floorJsonData)){ JSONObject jsonObject = JSON.parseObject(floorJsonData); angel = jsonObject.getFloat("angle"); compass = jsonObject.getFloat("compass"); } //处理户型图数据 //上传floorplan_user.json文件 FileUtils.writeFile(localDataPath + "floorplan_user.json", floorJsonData); fYunFileService.uploadFile(bucket, localDataPath + "floorplan_user.json", editUserPath + "floorplan_user.json"); //写入数据库 Byte floorPlanUser = null; if(StrUtil.isNotEmpty(floorJsonData)){ JSONObject houseTypeJson = CreateHouseJsonUtil .createHouseTypeJsonByUser(localDataPath + "floorplan_user.json"); fYunFileService.uploadFile(bucket, houseTypeJson.toJSONString().getBytes(), editUserPath + "houseType.json"); floorPlanUser = CommonStatus.YES.code(); } SceneEditInfo sceneEditInfoDb = this.getByScenePlusId(scenePlus.getId()); if(Objects.nonNull(sceneEditInfoDb)){ LambdaUpdateWrapper
保证马赛克数据安全性,当redis宕机导致热点数据丢失时,可以从文件中读取,恢复到redis
**/
private void syncMosaicFromFileToRedis(String num) throws Exception{
String key = String.format(RedisKey.SCENE_MOSAIC_DATA, num);
boolean exist = redisUtil.hasKey(key);
if(exist){
return;
}
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);
}
try{
exist = redisUtil.hasKey(key);
if(exist){
return;
}
String filePath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num);
String mosaicData = FileUtils.readFile(filePath + "mosaic.json");
if(StrUtil.isEmpty(mosaicData)){
return;
}
JSONArray jsonArray = JSON.parseArray(mosaicData);
if(CollUtil.isEmpty(jsonArray)){
return;
}
Map
保证马赛克数据安全性,当redis宕机导致热点数据丢失时,可以从文件中读取,恢复到redis
**/
private void writeMosaic(String num) throws Exception{
String mosaicPath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + "mosaic.json";
String key = String.format(RedisKey.SCENE_MOSAIC_DATA, num);
Map
热点数据保存
*
保证icons数据安全性,当redis宕机导致icons数据丢失时,可以从文件中读取,恢复到redis
*
保证热点数据安全性,当redis宕机导致热点数据丢失时,可以从文件中读取,恢复到redis
*