package com.fdkankan.fusion.down; import cn.hutool.core.io.FileUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.deepoove.poi.XWPFTemplate; import com.fdkankan.fusion.common.FilePath; import com.fdkankan.fusion.common.ResultData; import com.fdkankan.fusion.common.util.ShellUtil; import com.fdkankan.fusion.common.util.UploadToOssUtil; import com.fdkankan.fusion.entity.*; import com.fdkankan.fusion.httpClient.LaserService; import com.fdkankan.fusion.httpClient.response.FdkkResponse; import com.fdkankan.fusion.request.CaseParam; import com.fdkankan.fusion.response.DownVo; import com.fdkankan.fusion.response.DownloadProcessVo; import com.fdkankan.fusion.response.FusionNumVo; import com.fdkankan.fusion.response.SceneVo; import com.fdkankan.fusion.service.*; import com.fdkankan.fusion.service.impl.DownService; import com.fdkankan.redis.util.RedisUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.io.File; import java.io.FileOutputStream; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.HashSet; import java.util.List; @Service @Slf4j public class CaseDownService { @Value("${server.servlet.context-path}") String basePath; public static String jsonDataName = "data.json"; public static String caseInfo = "/case/getInfo?caseId="; public static String caseSettingsInfo = "/caseSettings/info?caseId="; public static String hostIcon = "/edit/hotIcon/list?caseId="; public static String caseView = "/caseView/allList?caseId="; public static String caseFiles = "/caseFiles/allList?caseId="; public static String caseFilesType = "/caseFilesType/allList?caseId="; public static String caseScene = "/case/sceneList?caseId="; public static String caseFusion = "/caseFusion/list?caseId="; public static String caseVideoFolder = "/caseVideoFolder/allList?caseId="; public static String caseVideo = "/caseVideo/allList?folderId="; public static String caseTag = "/caseTag/allList?caseId="; public static String caseTagPoint = "/caseTagPoint/allList?tagId="; public static String caseInquest = "/caseInquest/info?caseId="; public static String caseExtractDetail = "/caseExtractDetail/info?caseId="; public static String fusionGuide = "/fusionGuide/allList?caseId="; public static String fusionGuidePath = "/fusionGuidePath/allList?guideId="; public static String fusionMeter = "/fusionMeter/allList?fusionId="; public static String model = "/model/getInfo?modelId="; public static String caseImg = "/caseImg/getFfmpegImage?caseId="; public static String casePathInfoUrl = "/casePath/info?caseId="; public static String caseAnimationUrl = "/caseAnimation/list?caseId="; public static String getMapConfig = "/notAuth/getMapConfig"; public static String laserData = "/laser/dataset/%s/getDataSet"; public static String laserDataSetAndControlPoint = "/laser/4dage/%s/getDataSetAndControlPoint"; public static String laserDataQuery = "/laser/filter/%s/query?datasetId=%s"; @Autowired ICaseService caseService; @Autowired ICaseSettingsService caseSettingsService; @Autowired IFusionNumService fusionNumService; @Autowired ICaseViewService caseViewService; @Autowired ICaseVideoFolderService caseVideoFolderService; @Autowired ICaseVideoService caseVideoService; @Autowired ICaseFilesService caseFilesService; @Autowired ICaseFilesTypeService caseFilesTypeService; @Autowired IHotIconService hotIconService; @Autowired ICaseTagService caseTagService; @Autowired ICaseTagPointService caseTagPointService; @Autowired IFusionGuideService fusionGuideService; @Autowired IFusionGuidePathService fusionGuidePathService; @Autowired ICaseInquestService caseInquestService; @Autowired ICaseExtractDetailService caseExtractDetailService; @Autowired IFusionMeterService fusionMeterService; @Autowired IModelService modelService; @Autowired LaserService laserService; @Autowired ICaseOfflineService caseOfflineService; @Autowired ICaseImgService caseImgService; @Autowired ICasePathService casePathService; @Autowired ICaseAnimationService animationService; @Autowired IMapConfigService mapConfigService; @Autowired RedisUtil redisUtil; @Value("${spring.profiles.active}") private String environment; public static String downProcessKey = "fusion:down:offline:process:caseId:%s"; public DownVo checkDown(Integer caseId) { DownVo downVo = new DownVo(); // CaseOffline byCaseId = caseOfflineService.getByCaseId(caseId); // if(byCaseId != null){ // downVo.setDownloadStatus(3); // downVo.setDownloadUrl(byCaseId.getOfflineUrl()); // } return downVo; } @Async public void downOffline(Integer caseId){ String path = "/mnt/fusion/offline"; String name = "offline_"+ caseId; String zipName = path+File.separator+name+".zip"; try { String redisKey = String.format(downProcessKey, caseId); if( redisUtil.hasKey(redisKey)){ String res = redisUtil.get(redisKey); DownloadProcessVo downloadProcessVo = JSONObject.parseObject(res, DownloadProcessVo.class); if(downloadProcessVo.getStatus() != 1003 && (downloadProcessVo.getPercent()== null || downloadProcessVo.getPercent() != 100)){ return; } } setRedisProcess(caseId,0); //复制前端资源 cpIndexHtml(caseId); setRedisProcess(caseId,10); //创建data.json并下载资源 createDataJson(caseId); setRedisProcess(caseId,50); //打包zip ShellUtil.zipOffline(zipName,name); setRedisProcess(caseId,70); //上传oss String ossUrl = zipName.replace("/mnt/", ""); ShellUtil.yunUpload(zipName,ossUrl); ossUrl = queryPath + ossUrl; caseOfflineService.saveByCase(caseId,ossUrl); setRedisProcess(caseId,100,ossUrl); }catch (Exception e){ setRedisProcess(caseId,0,null,1003); log.info("down-offline-error:{}",caseId,e); }finally { try { if(new File(zipName).exists()){ new File(zipName).delete(); } if(new File(path+File.separator+name).exists()){ new File(path+File.separator+name).delete(); } }catch (Exception e){ log.info("down-offline-del-error:{}",caseId,e); } } } public void setRedisProcess(Integer caseId,Integer num){ setRedisProcess(caseId,num,null,1000); } public void setRedisProcess(Integer caseId,Integer num,String url){ setRedisProcess(caseId,num,url,1000); } public void setRedisProcess(Integer caseId,Integer num,String url,Integer status){ String redisKey = String.format(downProcessKey, caseId); log.info("down-offline-process:{},{},{}",caseId,num,url); DownloadProcessVo processVo = new DownloadProcessVo(); processVo.setStatus(status); processVo.setPercent(num); processVo.setUrl( url); redisUtil.set(redisKey,JSONObject.toJSONString(processVo)); } public DownloadProcessVo process(Integer caseId) { DownloadProcessVo downVo = new DownloadProcessVo(); String redisKey = String.format(downProcessKey, caseId); if(redisUtil.hasKey(redisKey)){ return JSONObject.parseObject(redisUtil.get(redisKey),DownloadProcessVo.class); } return downVo; } public void createDataJson(Integer caseId){ log.info("down-offline-createDataJson:{}",caseId); JSONObject jsonObject = new JSONObject(); CaseParam param = new CaseParam(); param.setCaseId(caseId); HashMap replaceMap = new HashMap<>(); //设置案件信息 jsonObject.put(basePath+caseInfo+caseId, ResultData.ok(caseService.getInfo(caseId,false))); List caseSettings = caseSettingsService.getByCaseId(caseId); jsonObject.put(basePath+caseSettingsInfo+caseId, ResultData.ok(caseSettings)); for (CaseSettings caseSetting : caseSettings) { downResource(caseId,caseSetting.getBack()); downResource(caseId,caseSetting.getCover()); } List listByCaseId = fusionNumService.getListByCaseId(caseId,null); jsonObject.put(basePath+caseFusion+caseId, ResultData.ok(listByCaseId)); for (FusionNumVo fusion : listByCaseId) { jsonObject.put(basePath+fusionMeter+fusion.getFusionId(), ResultData.ok(fusionMeterService.getListByFusionId(fusion.getFusionId(),null))); } for (FusionNumVo fusionNumVo : listByCaseId) { //下载媒体库模型 if(fusionNumVo.getSceneData() != null){ if(fusionNumVo.getSceneData().getType() ==3 && StringUtils.isNotBlank(fusionNumVo.getSceneData().getModelGlbUrl()) ){ downModel(caseId,fusionNumVo.getSceneData().getModelGlbUrl()); } } } List sceneVos = caseService.sceneList(param); for (SceneVo sceneData : sceneVos) { addReplaceMap(sceneData,replaceMap); //下载模型 if(StringUtils.isNotBlank(sceneData.getModelGlbUrl())){ downModel(caseId,sceneData.getModelGlbUrl()); } if(sceneData.getType() != 3){ //下载场景离线包 downSwkk(caseId,sceneData.getNum(),sceneData.getType()); } if(sceneData.getType() == 2 || sceneData.getType() == 5){ FdkkResponse sceneInfo = laserService.getSceneInfo(sceneData.getNum()); HashSet dataSetIds = new HashSet<>(); if(sceneInfo != null){ JSONArray jsonArray = JSONArray.parseArray(JSONArray.toJSONString(sceneInfo.getData())); JSONArray newJsonArray = new JSONArray(); for (Object object : jsonArray) { JSONObject sceneInfoObj = (JSONObject) object; String newPath = String.format(FilePath.OFFLINE_LASER_OSS_PATH, sceneData.getNum(), sceneData.getNum()); String oldPath = sceneInfoObj.getString("webBin"); sceneInfoObj.put("oldWebBin",oldPath); sceneInfoObj.put("webBin",newPath + oldPath); newJsonArray.add(sceneInfoObj); dataSetIds.add( sceneInfoObj.getString("id")); } sceneInfo.setData(newJsonArray); jsonObject.put(String.format(laserData,sceneData.getNum()),sceneInfo); if(!dataSetIds.isEmpty()){ for (String dataSetId : dataSetIds) { FdkkResponse sceneInfo2 = laserService.getSceneInfoQuery(sceneData.getNum(),dataSetId); jsonObject.put(String.format(laserDataQuery,sceneData.getNum(),dataSetId),sceneInfo2); } } } FdkkResponse dataSetAndControlPoint = laserService.getDataSetAndControlPoint(sceneData.getNum()); if(dataSetAndControlPoint !=null){ jsonObject.put(String.format(laserDataSetAndControlPoint,sceneData.getNum()),dataSetAndControlPoint); } } if(sceneData.getModelId() != null){ SceneVo info = modelService.getInfo(sceneData.getModelId()); jsonObject.put(basePath+model+sceneData.getModelId(), ResultData.ok(info)); } } jsonObject.put(basePath+caseScene+caseId, ResultData.ok(sceneVos)); List caseViews = caseViewService.allList(caseId, null, null, null, null); jsonObject.put(basePath+caseView+caseId, ResultData.ok(caseViews)); for (CaseView view : caseViews) { downResource(caseId,view.getViewImg()); downResource(caseId,view.getViewImgSmall()); } List videoFolders = caseVideoFolderService.getAllList(caseId); jsonObject.put(basePath+caseVideoFolder+caseId, ResultData.ok(videoFolders)); for (CaseVideoFolder videoFolder : videoFolders) { downResource(caseId,videoFolder.getVideoFolderCover()); downResource(caseId,videoFolder.getVideoMergeUrl()); List allList = caseVideoService.getAllList(videoFolder.getVideoFolderId()); for (CaseVideo video : allList) { downResource(caseId,video.getVideoCover()); downResource(caseId,video.getVideoPath()); } jsonObject.put(basePath+caseVideo+videoFolder.getVideoFolderId(), ResultData.ok(allList)); } List caseFilesList = caseFilesService.allList(caseId, null); for (CaseFiles files : caseFilesList) { if(StringUtils.isNotBlank(files.getFilesUrl())){ downResourceParent(caseId,files.getFilesUrl()); } } jsonObject.put(basePath+caseFiles+caseId, ResultData.ok(caseFilesList)); jsonObject.put(basePath+caseFilesType+caseId, ResultData.ok(caseFilesTypeService.list())); List hotIconList = hotIconService.getListByCaseId(caseId); for (HotIcon hotIcon : hotIconList) { downResource(caseId,hotIcon.getIconUrl()); } jsonObject.put(basePath+hostIcon+caseId, ResultData.ok(hotIconList)); List caseTagList = caseTagService.allList(caseId, null); jsonObject.put(basePath+caseTag+caseId, ResultData.ok(caseTagList)); for (CaseTag tag : caseTagList) { jsonObject.put(basePath+caseTagPoint+tag.getTagId(), ResultData.ok(caseTagPointService.allList(tag.getTagId()))); downResources(caseId,tag.getTagImgUrl()); downResource(caseId,tag.getHotIconUrl()); downResource(caseId,tag.getAudio()); } jsonObject.put(basePath+casePathInfoUrl+caseId, ResultData.ok(casePathService.getByCaseId(caseId))); List fusionGuides = fusionGuideService.getAllList(caseId); jsonObject.put(basePath+fusionGuide+caseId, ResultData.ok(fusionGuides)); for (FusionGuide guide : fusionGuides) { downResource(caseId,guide.getCover()); List listByGuideId = fusionGuidePathService.getListByGuideId(guide.getFusionGuideId()); for (FusionGuidePath guidePath : listByGuideId) { downResource(caseId,guidePath.getCover()); } jsonObject.put(basePath+fusionGuidePath+guide.getFusionGuideId(), ResultData.ok(listByGuideId)); } CaseInquest caseInquest1 = caseInquestService.getByCaseId(caseId); if(caseInquest1 != null){ XWPFTemplate inquestTemp = caseInquestService.getWordByTemplate(caseInquest1); downWordByTemplate(caseId,inquestTemp,"caseInquest.doc"); } jsonObject.put(basePath+caseInquest+caseId, ResultData.ok(caseInquest1)); CaseExtractDetail caseExtractDetail1 = caseExtractDetailService.getByCaseId(caseId); if(caseExtractDetail1 != null){ XWPFTemplate detailTemp = caseExtractDetailService.getWordByTemplate(caseExtractDetail1); downWordByTemplate(caseId,detailTemp,"caseExtractDetail.doc"); } jsonObject.put(basePath+caseExtractDetail+caseId, ResultData.ok(caseExtractDetail1)); List caseImgList = caseImgService.getByCaseId(caseId, 1); for (CaseImg img : caseImgList) { downResource(img.getCaseId(),img.getImgUrl()); } jsonObject.put(basePath+caseImg+caseId, ResultData.ok(caseImgList)); List list = animationService.getListByCaseId(caseId); for (CaseAnimation caseAnimation : list) { if(StringUtils.isNotBlank(caseAnimation.getUrl())){ downResource(caseId,caseAnimation.getUrl()); } } jsonObject.put(basePath+caseAnimationUrl+caseId, ResultData.ok(list)); jsonObject.put(basePath+getMapConfig, ResultData.ok(mapConfigService.list())); String jsonString = JSON.toJSONString(jsonObject); jsonString = jsonString.replaceAll(queryPath,"/oss/"); if(!replaceMap.isEmpty()){ for (String key : replaceMap.keySet()) { jsonString = jsonString.replaceAll(key,replaceMap.get(key)); } } FileUtil.writeString(jsonString, FilePath.OFFLINE_PACKAGE_PATH+caseId+"/www/package/"+jsonDataName,"UTF-8"); } private void addReplaceMap(SceneVo sceneData,HashMap map) { if(StringUtils.isNotBlank(sceneData.getCutModelPath())){ map.put(sceneData.getCutModelPath(),sceneData.getCutModelPath().replace("/oss/","/swkk/"+sceneData.getNum()+"/wwwroot/")); } if(StringUtils.isNotBlank(sceneData.getSurveillancePath())){ map.put(sceneData.getSurveillancePath(),sceneData.getSurveillancePath().replace("/oss/","/swkk/"+sceneData.getNum()+"/wwwroot/")); } if(StringUtils.isNotBlank(sceneData.getSceneJsonPath())){ map.put(sceneData.getSceneJsonPath(),sceneData.getSceneJsonPath().replace("/oss/","/swkk/"+sceneData.getNum()+"/wwwroot/")); } } //http://127.0.0.1:8080/offline.html?caseId=362&app=1&share=1#/show/summary static String batName = "start-browser.bat"; public void cpIndexHtml(Integer caseId){ log.info("down-offline-cpIndexHtml:{}",caseId); String caseOfflinePath = FilePath.OFFLINE_PACKAGE_PATH+caseId; FileUtil.copyContent(new File(FilePath.OFFLINE_TEMPLATE_PATH),new File(caseOfflinePath),true); String s = FileUtil.readString(caseOfflinePath + File.separator + batName, StandardCharsets.UTF_8); String s1 = s.replaceAll("@caseId", String.valueOf(caseId)); CaseEntity caseEntity = caseService.getById(caseId); if(caseEntity.getTmProjectId() == null){ s1 = s1.replaceAll("app=1", "app=2"); s1 = s1.replaceAll("isSample=0", "isSample=1"); } FileUtil.writeString(s1, caseOfflinePath + File.separator + batName,"UTF-8"); } @Autowired DownService downService; @Autowired UploadToOssUtil uploadToOssUtil; public void downSwkk(Integer caseId,String num,Integer type){ String swkkPath = FilePath.OFFLINE_PACKAGE_PATH+caseId + "/www/swkk/"+num; String swkkZipPath = swkkPath +".zip"; String swssPath = FilePath.OFFLINE_PACKAGE_PATH+caseId + "/www/swss/"+num; String swssZipPath = swssPath +".zip"; Integer isObj = 0; if(type == 4 || type == 6){ isObj =1; } try { DownVo downVo = downService.checkDownLoad(num, isObj,"offline"); log.info("down:{}",downVo); if(downVo.getDownloadStatus() == 3 && StringUtils.isNotBlank(downVo.getDownloadUrl())){ downZip(type,downVo.getDownloadUrl(),swkkZipPath,swkkPath,swssZipPath,swssPath); }else { DownVo down = downService.down(num, isObj,"offline"); if(down.getDownloadStatus() == 1){ DownloadProcessVo downloadProcessVo = downService.downloadProcess(num, isObj); while (downloadProcessVo.getStatus() != 1002 ){ downloadProcessVo = downService.downloadProcess(num, isObj); Thread.sleep(2000L); } downZip(type,downloadProcessVo.getUrl(),swkkZipPath,swkkPath,swssZipPath,swssPath); } } }catch (Exception e){ log.info("下载场景离线包失败:{}",num,e); } } @Value("${upload.query-path}") private String queryPath; @Value("${upload.query-path-ss}") private String ssQueryPath; public void downZip(Integer type ,String uri,String kkzipPath,String kknumPath,String sszipPath,String ssNumPath){ try { if(type != 2 && type != 5){ //深时点云 if(uri.contains("?")){ uri = uri.split("[?]")[0]; } ShellUtil.yunDownload(uri.replace(queryPath, ""), kkzipPath); ShellUtil.unZip(kkzipPath,kknumPath); }else { // {"msg":"操作成功","code":200,"data":{"status":1," // url":"https://laser-oss.4dkankan.com/testdata/SS-t-bY7NMQYlm6v/data/SS-t-bY7NMQYlm6v_offline18826401790 ShellUtil.yunDownloadSs(uri.replace(ssQueryPath, ""), sszipPath); ShellUtil.unZip(sszipPath,ssNumPath); } }catch (Exception e){ log.info("下载场景离线包失败:{}",uri,e); }finally { if(kkzipPath != null && new File(kkzipPath).exists()){ new File(kkzipPath).delete(); } if(sszipPath != null && new File(sszipPath).exists()){ new File(sszipPath).delete(); } } } public void downModel(Integer caseId, String modelGlbUrl) { String path = String.format(FilePath.OFFLINE_OSS_PATH,caseId); JSONArray jsonArray = JSONArray.parseArray(modelGlbUrl); for (Object object : jsonArray) { String res = (String) object; log.info("下载模型:{}",res); res = res.replace(queryPath, ""); if(res.contains(".json") || res.contains(".obj")){ res = new File(res).getParentFile().getPath(); } String desPath = path + "/oss/" + res; if(!desPath.contains(".")){ ShellUtil.yunDownload(res, new File(desPath).getParentFile().getPath()); return; } ShellUtil.yunDownload(res, desPath); } } public void downResources(Integer caseId,String urls) { JSONArray jsonArray = JSONArray.parseArray(urls); for (Object object : jsonArray) { String res = (String) object; downResource(caseId,res); } } public void downResource(Integer caseId,String url) { if(StringUtils.isBlank(url) ){ return; } url = url.replace(queryPath, ""); String path = String.format(FilePath.OFFLINE_OSS_PATH,caseId); String desPath = path + "/oss/" + url; if(!desPath.contains(".")){ ShellUtil.yunDownload(url, new File(desPath).getParentFile().getPath()); return; } ShellUtil.yunDownload(url,desPath); } public void downResourceParent(Integer caseId,String url) { if(StringUtils.isBlank(url) ){ return; } url = url.replace(queryPath, ""); String path = String.format(FilePath.OFFLINE_OSS_PATH,caseId); String desPath = path + "/oss/" + url; ShellUtil.yunDownload(new File(url).getParentFile().getPath(), new File(desPath).getParentFile().getParentFile().getPath()); } public void downWordByTemplate(Integer caseId,XWPFTemplate template,String name){ // 指定输出文件的路径 String outputPath = String.format(FilePath.OFFLINE_RESOURCE_PACKAGE_PATH,caseId) + name; File file = new File(outputPath); if(!file.getParentFile().exists()){ file.getParentFile().mkdirs(); } try { FileOutputStream out = new FileOutputStream(outputPath); template.write(out); out.close(); log.info("文档已成功写入到: " + outputPath); } catch (Exception e) { log.info("写出文档失败:{},{}",caseId,name,e); } } }