package com.fdkankan.contro.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.fdkankan.common.util.FileUtils; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.fdkankan.common.constant.CommonStatus; import com.fdkankan.common.constant.PayStatus; import com.fdkankan.common.constant.SceneStatus; import com.fdkankan.common.constant.SpaceType; import com.fdkankan.common.util.FileUtils; import com.fdkankan.contro.bean.SceneJsonBean; import com.fdkankan.contro.entity.*; import com.fdkankan.contro.factory.UserEditData.UserEditDataHandler; import com.fdkankan.contro.factory.UserEditData.UserEditDataHandlerFactory; import com.fdkankan.contro.service.ICommonService; import com.fdkankan.contro.service.*; import com.fdkankan.contro.vo.SceneEditControlsVO; import com.fdkankan.contro.vo.ScenePlusVO; import com.fdkankan.fyun.config.FYunFileConfig; import com.fdkankan.fyun.face.FYunFileServiceInterface; import com.fdkankan.model.constants.ConstantFilePath; import com.fdkankan.model.constants.UploadFilePath; import com.fdkankan.model.utils.FloorPlanUserUtil; import com.fdkankan.rabbitmq.bean.BuildSceneCallMessage; import com.fdkankan.rabbitmq.util.RabbitMqProducer; import com.fdkankan.redis.constant.RedisKey; import com.fdkankan.redis.util.RedisUtil; import com.fdkankan.sms.SendMailAcceUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; 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 javax.annotation.Resource; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.Objects; import java.util.*; import java.util.stream.Collectors; @Slf4j @Service @RefreshScope public class CommonServiceImpl implements ICommonService { @Value("${main.url}") private String mainUrl; @Value("${env:gn}") private String env; @Value("${helpLink.zh-cn:https://docs.4dkankan.com/#/product/4dkk/zh-cn/README}") private String helpLinkZh; @Value("${helpLink.en-us:https://docs.4dkankan.com/#/product/4dkk/en-us/README}") private String helpLinkEn; @Value("#{'${camType.laser:}'.split(',')}") private List laserCamTypeList; @Value("${build.status.url}") private String sceneStatusUrl; @Autowired private ISceneAsynOperLogService sceneAsynOperLogService; @Autowired private IScenePlusService scenePlusService; @Autowired private IScenePlusExtService scenePlusExtService; @Autowired private IMailTemplateService mailTemplateService; @Autowired private IUserService userService; @Autowired private ISceneProService sceneProService; @Autowired private ICameraDetailService cameraDetailService; @Autowired private IUserIncrementService userIncrementService; @Autowired private IIncrementTypeService incrementTypeService; @Autowired private ICameraService cameraService; @Autowired private FYunFileServiceInterface fYunFileService; @Autowired private FYunFileConfig fYunFileConfig; @Autowired private ISceneEditInfoService sceneEditInfoService; @Autowired private ISceneEditControlsService sceneEditControlsService; @Autowired private ISceneEditInfoExtService sceneEditInfoExtService; @Autowired private RedisUtil redisUtil; @Autowired private IMqSendLogService mqSendLogService; @Autowired private RabbitMqProducer rabbitMqProducer; @Autowired private ISceneInfoSyncMqConfigService sceneInfoSyncMqConfigService; @Override public void uploadBuildResultData(String num, String dataSource, String version) { Map uploadMap = new HashMap<>(); String ossResultPath = String.format(UploadFilePath.scene_result_data_path, num); //删除旧的文件目录 fYunFileService.deleteFolder(ossResultPath); //上传caches/images String localCachesImagePath = dataSource + "/caches/images/"; String ossCachesImagePath = ossResultPath + "caches/images/"; //先清除旧的全景图 if(FileUtil.exist(localCachesImagePath)){ fYunFileService.uploadFileByCommand(localCachesImagePath, ossCachesImagePath); } //上传project.json String localProjectJsonPath = dataSource + "/project.json"; String ossProjectJsonPath = ossResultPath + "project.json"; if(FileUtil.exist(localProjectJsonPath)){ uploadMap.put(localProjectJsonPath, ossProjectJsonPath); } //上传data.json String localDataJsonPath = dataSource + "/data.json"; String ossDataJsonPath = ossResultPath + "data.json"; if(FileUtil.exist(localDataJsonPath)){ uploadMap.put(localDataJsonPath, ossDataJsonPath); } //户型图上传 String floorplanCadPath = ossResultPath + "floorplan_cad"; String cadPicPathFormat = floorplanCadPath + "/floor-cad-%s.%s"; String floorCadPath = dataSource + "/results/floorplan_cad"; //清除原有旧的cad图 fYunFileService.deleteFolder(floorplanCadPath); List floorCadList = FileUtils.getFileList(floorCadPath); if(CollUtil.isNotEmpty(floorCadList)){ floorCadList.stream().forEach(str->{ String substring = str.substring(str.lastIndexOf(File.separator) + 1); String[] arr = substring.split("floor"); String[] arr2 = arr[1].split("\\."); //上传到用户编辑目录 uploadMap.put(str, String.format(cadPicPathFormat, arr2[0], arr2[1])); }); } //上传深时场景生成obj需要的文件 String localReconstruction = dataSource + "/caches/reconstruction/"; String ossReconstruction = ossResultPath + "caches/reconstruction/"; if(FileUtil.exist(localReconstruction)){ fYunFileService.uploadFileByCommand(localReconstruction, ossReconstruction); } String localDepthmap = dataSource + "/caches/depthmap/"; String ossDepthmap = ossResultPath + "caches/depthmap/"; if(FileUtil.exist(localDepthmap)){ fYunFileService.uploadFileByCommand(localDepthmap, ossDepthmap); } String localDepthmapAsc = dataSource + "/caches/depthmap_csc/"; String ossDepthmapAsc = ossResultPath + "caches/depthmap_csc/"; if(FileUtil.exist(localDepthmapAsc)){ fYunFileService.uploadFileByCommand(localDepthmapAsc, ossDepthmapAsc); } String localPanoramaJson = dataSource + "/caches/panorama.json"; String ossPanoramaJson = ossResultPath + "caches/panorama.json"; if(FileUtil.exist(localPanoramaJson)){ fYunFileService.uploadFile(localPanoramaJson, ossPanoramaJson); } // String localLaserPly = dataSource + "/results/laserData/laser.ply"; // String ossLaserPly = ossResultPath + "results/laserData/laser.ply"; // if(FileUtil.exist(localLaserPly)){ // fYunFileServiceInterface.uploadFile(localLaserPly, ossLaserPly); // } String localFloorGroupFixJson = dataSource + "/caches/floor_group_fix.json"; String ossFloorGroupFixJson = ossResultPath + "caches/floor_group_fix.json"; if(FileUtil.exist(localFloorGroupFixJson)){ fYunFileService.uploadFile(localFloorGroupFixJson, ossFloorGroupFixJson); } String localDepthmapVis = dataSource + "/caches/depthmap_vis"; String ossDepthmapVis = ossResultPath + "caches/depthmap_vis"; if(FileUtil.exist(localDepthmapVis)){ fYunFileService.uploadFileByCommand(localDepthmapVis, ossDepthmapVis); } String localIntensity = dataSource + "/caches/intensity"; String ossIntensity = ossResultPath + "caches/intensity"; if(FileUtil.exist(localIntensity)){ fYunFileService.uploadFileByCommand(localIntensity, ossIntensity); } //上传点位校准相关文件 String localExtras = dataSource + "/extras"; String ossExtras = ossResultPath + "extras"; if(FileUtil.exist(localExtras)){ fYunFileService.uploadFileByCommand(localExtras, ossExtras); } //开始上传 fYunFileService.uploadMulFiles(uploadMap); } @Override public void uploadFloorplanJson(String num, String dataSource) throws Exception{ String floorPlanCardFilePath = dataSource + File.separator + "results/floorplan_cad.json"; if (!new File(floorPlanCardFilePath).exists()) { log.warn("floorplan_cad.json 文件不存在,文件路径:{}", floorPlanCardFilePath); return; } JSONObject json = FloorPlanUserUtil.createFloorPlanUserJson(floorPlanCardFilePath); if(Objects.isNull(json)){ log.warn("生成floorplan.json失败,cadPath:{}", floorPlanCardFilePath); return; } String floorplanJsonPath = String.format(UploadFilePath.DATA_VIEW_PATH, num) + "floorplan.json"; fYunFileService.uploadFile(json.toJSONString().getBytes(), floorplanJsonPath); } @Override public void initUserEditData(String num, Set bizs, Map> params) throws Exception { if(StrUtil.isEmpty(num) || CollUtil.isEmpty(bizs)){ return; } for (String biz : bizs) { UserEditDataHandler handler = UserEditDataHandlerFactory.getHandler(biz); handler.init(num, CollUtil.isEmpty(params) ? null : params.get(biz)); } } @Override public void sendEmail(String num) { try { Long userId = null; String websize = ""; String title = ""; ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num); if(Objects.isNull(scenePlus)){ ScenePro scenePro = sceneProService.getByNum(num); if(Objects.isNull(scenePro)){ return; } userId = scenePro.getUserId(); websize = scenePro.getWebSite(); title = scenePro.getSceneName(); }else{ userId = scenePlus.getUserId(); ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId()); websize = scenePlusExt.getWebSite(); title = scenePlus.getTitle(); } if(Objects.isNull(userId)){ return; } User user = userService.getById(userId); if(Objects.isNull(user) || StrUtil.isEmpty(user.getUserName())){ return; } String toEmail = user.getUserName(); String helpLink = helpLinkEn; String lang = "en"; if("gn".equals(env)){ lang = "zh"; helpLink = helpLinkZh; } websize += "&lang=" + lang; MailTemplate mailTemplate = mailTemplateService.getOne(new LambdaQueryWrapper().eq(MailTemplate::getRemark, "计算完成").eq(MailTemplate::getLang, lang)); String content = mailTemplate.getMsg().replaceAll("scene_name", title).replaceAll("scene_link", websize).replaceAll("help_link", helpLink); SendMailAcceUtils.sendMail(mailTemplate.getSendMail(), mailTemplate.getSendPassword(), mailTemplate.getSendHost(), toEmail, mailTemplate.getSubject(), content, null); }catch (Exception e){ log.error("发送邮件失败,num:" + num, e); } } public String getOssOrignPath(String path) { String ossPath = ConstantFilePath.OSS_PREFIX + path.replace(ConstantFilePath.BUILD_MODEL_PATH, "") .replace(ConstantFilePath.BUILD_MODEL_LASER_PATH, ""); if (!ossPath.endsWith("/")) { ossPath = ossPath.concat("/"); } return ossPath; } @Override public int getPayStatus(Long cameraId, Long space){ //查询权益统计容量的方式 // String unit = SpaceType.GB.code(); // CameraDetail cameraDetail = cameraDetailService.getByCameraId(cameraId); // if(StrUtil.isNotEmpty(cameraDetail.getUnit())){ // unit = cameraDetail.getUnit(); // } // Long limit = this.getSpaceLimit(cameraDetail); // // if(SpaceType.SP.code().equals(unit)){//如果按空间方式统计,则space置为1 // space = 1L; // } // // //更新相机使用用量 // cameraDetailService.updateCameraDetailByCameraIdAndSpace(cameraId, space); // // if(limit == -1){ // return PayStatus.PAY.code(); // } // // Long usedSpace = cameraService.getUsedSpace(cameraId, unit); // if(usedSpace + space > limit){ // return PayStatus.NO_CAPACITY.code(); // } return PayStatus.PAY.code(); } @Override public void uploadStatusJson(String num, Integer sceneStatus, String webSite, String thumb, Integer payStatus, String uploadPath) { String localDataPath = String.format(ConstantFilePath.DATABUFFER_FORMAT, num); JSONObject statusJson = new JSONObject(); statusJson.put("status", sceneStatus); statusJson.put("webSite", webSite); statusJson.put("sceneNum", num); statusJson.put("thumb", thumb); statusJson.put("payStatus", PayStatus.NOT_PAY.code()); statusJson.put("recStatus", 'A'); FileUtils.writeFile(localDataPath + "status.json", statusJson.toString()); fYunFileService.uploadFile(localDataPath + "status.json", uploadPath + "status.json"); } @Override public Long getSpaceLimit(CameraDetail cameraDetail){ Long limit = cameraDetail.getTotalSpace(); UserIncrement userIncrement = userIncrementService.getByCameraId(cameraDetail.getCameraId()); if(Objects.nonNull(userIncrement) && userIncrement.getIsExpired() == CommonStatus.NO.code().intValue()){ IncrementType incrementType = incrementTypeService.getById(userIncrement.getIncrementTypeId()); switch (SpaceType.get(cameraDetail.getUnit())){ case GB: limit = incrementType.getCameraCapacity(); if(limit != -1){ limit = limit * 1024 * 1024 * 1024; } break; case SP: limit = incrementType.getCameraSpace(); break; } } return limit; } @Override public Long getSpace(String num){ Long space = fYunFileService.getSpace(fYunFileConfig.getBucket(), String.format(UploadFilePath.DATA_VIEW_PATH, num)); space += fYunFileService.getSpace(fYunFileConfig.getBucket(), String.format(UploadFilePath.IMG_VIEW_PATH, num)); space += fYunFileService.getSpace(fYunFileConfig.getBucket(), String.format(UploadFilePath.VIDEOS_VIEW_PATH, num)); space += fYunFileService.getSpace(fYunFileConfig.getBucket(), String.format(UploadFilePath.VOICE_VIEW_PATH, num)); space += fYunFileService.getSpace(fYunFileConfig.getBucket(), String.format(UploadFilePath.scene_result_data_path, num).concat("caches")); return space; } public Object[] updateEditInfo(ScenePlus scenePlus){ SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId()); SceneEditControls sceneEditControls = null; SceneEditInfoExt sceneEditInfoExt = null; if(sceneEditInfo == null){ sceneEditInfo = new SceneEditInfo(); sceneEditInfo.setScenePlusId(scenePlus.getId()); sceneEditInfo.setDescription(scenePlus.getDescription()); sceneEditInfo.setTitle(scenePlus.getTitle()); sceneEditInfoService.save(sceneEditInfo); }else{ int version = 0; int imgVersion = 0; int linkVersion = 0; //获取展示页的版本号 String sceneJsonStr = fYunFileService.getFileContent(String.format(UploadFilePath.DATA_VIEW_PATH, scenePlus.getNum()) + "scene.json"); if(StrUtil.isNotEmpty(sceneJsonStr)){ JSONObject sceneJson = JSON.parseObject(sceneJsonStr); version = sceneJson.getIntValue("version"); imgVersion = sceneJson.getIntValue("imgVersion"); linkVersion = sceneJson.getIntValue("linkVersion"); } if(version < sceneEditInfo.getVersion()){ version = sceneEditInfo.getVersion(); } if(imgVersion < sceneEditInfo.getImgVersion()){ imgVersion = sceneEditInfo.getImgVersion(); } if(linkVersion < sceneEditInfo.getLinkVersion()){ linkVersion = sceneEditInfo.getLinkVersion(); } sceneEditControls = sceneEditControlsService.getBySceneEditId(sceneEditInfo.getId()); sceneEditInfoExt = sceneEditInfoExtService.getByEditInfoId(sceneEditInfo.getId()); sceneEditInfo.setVersion(version + 1); sceneEditInfo.setImgVersion(imgVersion + 1); sceneEditInfo.setLinkVersion(linkVersion + 1); sceneEditInfo.setIsUploadObj(CommonStatus.NO.code()); sceneEditInfoService.updateById(sceneEditInfo); } if(sceneEditControls == null){ sceneEditControls = new SceneEditControls(); sceneEditControls.setEditInfoId(sceneEditInfo.getId()); sceneEditControlsService.save(sceneEditControls); } if(sceneEditInfoExt == null){ sceneEditInfoExt = new SceneEditInfoExt(); sceneEditInfoExt.setScenePlusId(scenePlus.getId()); sceneEditInfoExt.setEditInfoId(sceneEditInfo.getId()); sceneEditInfoExtService.save(sceneEditInfoExt); } return new Object[]{sceneEditInfo, sceneEditInfoExt, sceneEditControls}; } public void writeSceneJson(String num, JSONObject videosJson, SceneEditInfo sceneEditInfo, SceneEditInfoExt sceneEditInfoExt, SceneEditControls sceneEditControls, ScenePlus scenePlus, ScenePlusExt scenePlusExt,Company company){ String dataViewPath = String.format(UploadFilePath.DATA_VIEW_PATH, num); String oldSceneJson = fYunFileService.getFileContent(dataViewPath + "scene.json"); SceneJsonBean sceneJson = new SceneJsonBean(); BeanUtil.copyProperties(sceneEditInfoExt, sceneJson, "started"); BeanUtil.copyProperties(sceneEditInfo, sceneJson); SceneEditControlsVO sceneEditControlsVO = BeanUtil.copyProperties(sceneEditControls, SceneEditControlsVO.class); sceneJson.setControls(sceneEditControlsVO); sceneJson.setNum(num); sceneJson.setCreateTime(scenePlus.getCreateTime()); sceneJson.setSceneResolution(scenePlusExt.getSceneResolution()); sceneJson.setVersion(sceneEditInfo.getVersion()); sceneJson.setImgVersion(sceneEditInfo.getImgVersion()); sceneJson.setSceneFrom(scenePlusExt.getSceneFrom()); sceneJson.setSceneKind(scenePlusExt.getSceneKind()); sceneJson.setModelKind(scenePlusExt.getModelKind()); sceneJson.setVideos(JSON.toJSONString(videosJson)); sceneJson.setPayStatus(scenePlus.getPayStatus()); if(StrUtil.isNotEmpty(oldSceneJson)){ SceneJsonBean oldSceneJsonBean = JSON.parseObject(oldSceneJson, SceneJsonBean.class); List mosaicList = JSON.parseObject(oldSceneJson, SceneJsonBean.class).getMosaicList(); sceneJson.setMosaicList(mosaicList); sceneJson.setFloorLogo(oldSceneJsonBean.getFloorLogo()); sceneJson.setFloorLogoFile(oldSceneJsonBean.getFloorLogoFile()); sceneJson.setBoxModels(oldSceneJsonBean.getBoxModels()); sceneJson.setBoxVideos(oldSceneJsonBean.getBoxVideos()); sceneJson.setBoxPhotos(oldSceneJsonBean.getBoxPhotos()); } if(StrUtil.isNotEmpty(sceneEditInfoExt.getStarted())){ sceneJson.setStarted(JSON.parseObject(sceneEditInfoExt.getStarted())); } if(!ObjectUtils.isEmpty(company)){ String userViewPath = String.format(UploadFilePath.USER_VIEW_PATH, num); String userEditPath = String.format(UploadFilePath.USER_EDIT_PATH, num); String localLogoPath = null; if (StrUtil.isNotEmpty(company.getTopLogo())) { localLogoPath = ConstantFilePath.AGENT_PATH + company.getTopLogo().substring(company.getTopLogo().lastIndexOf("//") + 1); HttpUtil.downloadFile(company.getTopLogo(), localLogoPath); fYunFileService.uploadFile(localLogoPath, userViewPath + "loadingLogo-user.png"); fYunFileService.uploadFile(localLogoPath, userEditPath + "loadingLogo-user.png"); sceneJson.setLoadingLogo("user"); sceneJson.setLoadingLogoFile("loadingLogo-user.png"); sceneEditInfo.setLoadingLogo("user"); sceneEditInfo.setLoadingLogoFile("loadingLogo-user.png"); } if (StrUtil.isNotEmpty(company.getFloorLogo())) { localLogoPath = ConstantFilePath.AGENT_PATH + company.getFloorLogo().substring(company.getFloorLogo().lastIndexOf("//") + 1); HttpUtil.downloadFile(company.getFloorLogo(), localLogoPath); fYunFileService.uploadFile(localLogoPath, userViewPath + "floorLogo-user.png"); fYunFileService.uploadFile(localLogoPath, userEditPath + "floorLogo-user.png"); sceneJson.setFloorLogo("user"); sceneJson.setFloorLogoFile("floorLogo-user.png"); sceneEditInfo.setFloorLogo("user"); sceneEditInfo.setFloorLogoFile("floorLogo-user.png"); } if(!ObjectUtils.isEmpty(localLogoPath)){ sceneEditInfoService.updateById(sceneEditInfo); FileUtils.deleteFile(localLogoPath); } } String sceneJsonStr = JSON.toJSONString(sceneJson); //上传sceneJson文件 fYunFileService.uploadFile(sceneJsonStr.getBytes(), dataViewPath + "scene.json"); //scenejson写入缓存 redisUtil.set(String.format(RedisKey.SCENE_JSON, num), sceneJsonStr); } @Override public void saveMqSendLog(String num, BuildSceneCallMessage message) { MqSendLog mqSendLog = new MqSendLog(); mqSendLog.setNum(num); mqSendLog.setContent(JSON.toJSONString(message)); mqSendLogService.save(mqSendLog); } @Override public void sendUpdateSceneStatusMqToQueues(Map content) { List configs = sceneInfoSyncMqConfigService.listByInfoType("update_scene_status"); if(CollUtil.isEmpty(configs)){ return; } for (SceneInfoSyncMqConfig config : configs) { rabbitMqProducer.sendByWorkQueue(config.getQueueName(), content); } } @Override public void removeSceneAsynOperLog(String num) { List list = sceneAsynOperLogService.list(new LambdaQueryWrapper().eq(SceneAsynOperLog::getNum, num)); if(CollUtil.isEmpty(list)){ return; } //删除数据库记录 List deleteIdList = list.parallelStream().map(item -> item.getId()).collect(Collectors.toList()); sceneAsynOperLogService.removeByIds(deleteIdList); list.parallelStream().forEach(item -> { if(StrUtil.isNotEmpty(item.getUrl())){ try { fYunFileService.deleteFile(item.getUrl()); } catch (IOException e) { log.warn("删除oss全景图下载压缩包失败,key:{}", item.getUrl()); } } }); } /** * status 1-开始上传 2-通知计算, 3-开始计算 , 4-计算成功, 5-计算失败, * @param num * @param uuid * @param batchId * @param status */ @Override public void sendSceneStatus(String num, String uuid, String batchId,Integer status) { Map playload = new HashMap<>(); try { playload.put("num", num); playload.put("uuid", uuid); playload.put("status", status); playload.put("batchId", batchId); HttpUtil.post(sceneStatusUrl, playload, 2000); }catch (Exception exception){ log.error("推送计算状态失败, content:{}", playload); } } }