|
@@ -0,0 +1,592 @@
|
|
|
+package com.gis.listener.container;
|
|
|
+
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.io.FileUtil;
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.fdkankan.filestorage.FileStorageTemplate;
|
|
|
+import com.gis.constant.CmdConstant;
|
|
|
+import com.gis.constant.ConfigConstant;
|
|
|
+import com.gis.constant.RedisKey;
|
|
|
+import com.gis.constant.SysConstants;
|
|
|
+import com.gis.dto.*;
|
|
|
+import com.gis.entity.*;
|
|
|
+import com.gis.exception.BaseRuntimeException;
|
|
|
+import com.gis.mq.RabbitMqProducerUtil;
|
|
|
+import com.gis.oss.util.FileAndOssUtil;
|
|
|
+import com.gis.receiver.QueueNameService;
|
|
|
+import com.gis.service.*;
|
|
|
+import com.gis.util.CmdUtils;
|
|
|
+import com.gis.util.QrCodeUtils;
|
|
|
+import com.gis.util.RandomUtils;
|
|
|
+import com.gis.util.RedisUtil;
|
|
|
+import com.rabbitmq.client.Channel;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.slf4j.MDC;
|
|
|
+import org.springframework.amqp.core.Message;
|
|
|
+import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.util.ObjectUtils;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.io.File;
|
|
|
+import java.io.PrintWriter;
|
|
|
+import java.io.StringWriter;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.List;
|
|
|
+import java.util.concurrent.*;
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
|
+import java.util.regex.Matcher;
|
|
|
+import java.util.regex.Pattern;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author Xiewj
|
|
|
+ * @date 2025/3/19
|
|
|
+ */
|
|
|
+@Component
|
|
|
+@Slf4j
|
|
|
+public class SceneWorkQueueListener implements ChannelAwareMessageListener {
|
|
|
+ @Autowired
|
|
|
+ FodderService fodderService;
|
|
|
+ @Autowired
|
|
|
+ WorkService workService;
|
|
|
+ @Autowired
|
|
|
+ FileAndOssUtil fileAndOssUtil;
|
|
|
+ @Autowired
|
|
|
+ ConfigConstant configConstant;
|
|
|
+ @Autowired
|
|
|
+ QrCodeUtils qrCodeUtils;
|
|
|
+ @Autowired
|
|
|
+ ScenePanoService scenePanoService;
|
|
|
+ @Autowired
|
|
|
+ RabbitMqProducerUtil rabbitMqProducerUtil;
|
|
|
+ @Value("${queue.relics-init-queue}")
|
|
|
+ String relicsInitQueue;
|
|
|
+
|
|
|
+ @Value("${queue.scene-queue-work}")
|
|
|
+ String sceneQueueWork;
|
|
|
+ @Resource
|
|
|
+ private FileStorageTemplate ossUtil;
|
|
|
+ @Value("${domain.4dkk}")
|
|
|
+ public String domain4dKK;
|
|
|
+ @Autowired
|
|
|
+ WorkCoverTypeService workCoverTypeService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ WorkLogoService workLogoService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ WorkOpeningTipService workOpeningTipService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ WorkOpeningAnimationService workOpeningAnimationService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private WorkCustomMaskService workCustomMaskService;
|
|
|
+ @Autowired
|
|
|
+ QueueNameService queueNameService;
|
|
|
+ @Autowired
|
|
|
+ private WorkCustomButtonService workCustomButtonService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private WorkNavigationSettingService workNavigationSettingService;
|
|
|
+ @Autowired
|
|
|
+ private WorkNavigationService workNavigationService;
|
|
|
+
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ IMqEcsService mqEcsService;
|
|
|
+ @Autowired
|
|
|
+ RedisUtil redisUtil;
|
|
|
+ @Override
|
|
|
+ public void onMessage(Message message, Channel channel) throws Exception {
|
|
|
+
|
|
|
+ if (ObjectUtils.isEmpty(message.getBody())) {
|
|
|
+ log.error("消息内容为空,退出构建,当前服务器id:{}" );
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String traceId = System.currentTimeMillis()+"";
|
|
|
+ MDC.put("TRACE_ID", traceId);
|
|
|
+ String sceneCode="";
|
|
|
+ long deliveryTag = message.getMessageProperties().getDeliveryTag();
|
|
|
+ //计算暂停锁,计算中锁。弹性伸缩控制服务使用
|
|
|
+ String modelingKey = String.format(RedisKey.modelingKey,SysConstants.hostName);
|
|
|
+ String stopKey = String.format(RedisKey.ecsStopKey,SysConstants.hostName);
|
|
|
+ String messageId = message.getMessageProperties().getMessageId();
|
|
|
+ String msg = new String(message.getBody(), StandardCharsets.UTF_8);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ try {
|
|
|
+ log.error("服务实例:{} 正在构建!", SysConstants.hostName);
|
|
|
+ log.info("场景sceneQueueWork开始,队列名:{},id:{},deliveryTag:{},消息体:{}", queueNameService.getQueueName(), messageId,deliveryTag,msg);
|
|
|
+ //设置为计算超时时间过期
|
|
|
+ redisUtil.set(modelingKey,msg,SysConstants.modelTimeOut * 3600L,TimeUnit.SECONDS);
|
|
|
+ if(redisUtil.hasKey(stopKey)){
|
|
|
+ log.error("服务实例:{} 正在关闭,退出构建!", SysConstants.hostName);
|
|
|
+ redisUtil.delete(modelingKey);
|
|
|
+ channel.basicNack(deliveryTag, true, true);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ SceneQueueDTO param = JSONObject.parseObject(JSON.parse(msg).toString(), SceneQueueDTO.class);
|
|
|
+ if (ObjectUtil.isEmpty(param.getSceneCode())) {
|
|
|
+ log.error("参数列表错误(缺少),格式不匹配,{}",param);
|
|
|
+ channel.basicAck(deliveryTag, false);
|
|
|
+ }
|
|
|
+ sceneCode=param.getSceneCode();
|
|
|
+ WorkEntity workEntity=workService.findByNum(param.getSceneCode());
|
|
|
+ if (ObjectUtil.isNotEmpty(param.getSceneCode())&¶m.getStatus()==1){
|
|
|
+ updateOssStatusJson(param.getSceneCode(),0);
|
|
|
+
|
|
|
+ //计算完成处理
|
|
|
+ //1,下载场景的全景图 默认 。scene_view_data/panorama/目录下的全景图图片
|
|
|
+ workEntity.setAlgorithmTime(param.getAlgorithmTime());
|
|
|
+ workEntity.setCalcStatus(0);
|
|
|
+ if (ObjectUtil.isNotEmpty(param.getPayStatus())){
|
|
|
+ workEntity.setPayStatus(param.getPayStatus());
|
|
|
+ }
|
|
|
+ if (ObjectUtil.isNotEmpty(param.getSceneSource())){
|
|
|
+ workEntity.setSceneSource(param.getSceneSource());
|
|
|
+ }
|
|
|
+ if (ObjectUtil.isNotEmpty(param.getPwd())&&ObjectUtil.isEmpty(workEntity.getPassword())){
|
|
|
+ workEntity.setPassword(param.getPwd());
|
|
|
+ workEntity.setIsPassword(1);
|
|
|
+ }
|
|
|
+ workService.updateById(workEntity);
|
|
|
+ //清理旧数据
|
|
|
+ List<ScenePanoEntity> list = scenePanoService.findByWorkId(workEntity.getId());
|
|
|
+ for (ScenePanoEntity scenePanoEntity : list) {
|
|
|
+ scenePanoEntity.setIsDelete(1);
|
|
|
+ scenePanoEntity.setUpdateTime(new Date());
|
|
|
+ scenePanoService.updateById(scenePanoEntity);
|
|
|
+ }
|
|
|
+ String visionOssKey="scene_view_data/"+param.getSceneCode()+"/images/vision.txt";
|
|
|
+
|
|
|
+ JSONArray sweepLocations = new JSONArray();
|
|
|
+ if (ossUtil.doesObjectExist("4dkankan",visionOssKey)){
|
|
|
+ log.info("vision.txt存在: {}",visionOssKey);
|
|
|
+ JSONObject visJson = JSONObject.parseObject(ossUtil.getFileContent("4dkankan",visionOssKey));
|
|
|
+ if(visJson.containsKey("sweepLocations")){
|
|
|
+ sweepLocations = visJson.getJSONArray("sweepLocations");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //2,使用krpano工具生成全景图数据
|
|
|
+ List<InitWorkNavigationSceneDTO> scenes = new ArrayList<>();
|
|
|
+
|
|
|
+ for (int i = 0; i < sweepLocations.size(); i++) {
|
|
|
+ JSONObject jsonObject = sweepLocations.getJSONObject(i);
|
|
|
+ String uuid = jsonObject.getString("uuid");
|
|
|
+ String id = jsonObject.getString("id");
|
|
|
+ String ossKey="scene_view_data/"+param.getSceneCode()+"/images/panoramas/"+uuid+".jpg";
|
|
|
+ InitWorkNavigationSceneDTO scene=new InitWorkNavigationSceneDTO();
|
|
|
+ ScenePanoEntity scenePanoEntity = this.doSlice(traceId ,ossKey, param.getSceneCode(), workEntity.getId(),uuid+".jpg",uuid,id);
|
|
|
+ // "icon": "https://ossxiaoan.4dage.com/720yun_fd_manage/fd720_8nRkFlzpp/vtour/panos/fd720_8nRkFlzpp.tiles/thumb.jpg",
|
|
|
+ // "sceneCode": "fd720_8nRkFlzpp",
|
|
|
+ // "sceneTitle": "0",
|
|
|
+ // "category": 1,
|
|
|
+ // "type": "pano",
|
|
|
+ // "id": "s_xId8vevp",
|
|
|
+ scene.setIcon(scenePanoEntity.getIcon());
|
|
|
+ scene.setType("pano");
|
|
|
+ scene.setName(id);
|
|
|
+ //id生成规则是 s_ 拼接,随机8位字符串,字母加数字组合,有大小写
|
|
|
+ scene.setSceneCode(scenePanoEntity.getSceneCode());
|
|
|
+ scenes.add(scene);
|
|
|
+ if (i==0){
|
|
|
+ workEntity.setIcon(scenePanoEntity.getIcon());
|
|
|
+ workService.updateById(workEntity);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("场景切图完成组装json");
|
|
|
+ //修改为创建数据库
|
|
|
+ String shareUrl = configConstant.domain4dKK + "/panorama/showMobile.html?id=" + workEntity.getId();
|
|
|
+ String qrCode = qrCodeUtils.generateLogoQrCode(shareUrl, configConstant.serverBasePath, configConstant.ossBasePath, ossUtil.calculateUrl(""), workEntity.getId());
|
|
|
+ workEntity.setQrCode(qrCode);
|
|
|
+ workEntity.setShare(shareUrl);
|
|
|
+
|
|
|
+ //创建tour.xml
|
|
|
+ this.saveTour(workEntity.getId());
|
|
|
+
|
|
|
+ WorkAddDto workAddDto = new WorkAddDto();
|
|
|
+ workAddDto.setSceneDTOList(scenes);
|
|
|
+
|
|
|
+ this.initData(workAddDto, workEntity);
|
|
|
+
|
|
|
+ workEntity.setCalcStatus(1);
|
|
|
+ workService.updateById(workEntity);
|
|
|
+ sendEndMq(param);
|
|
|
+ updateOssStatusJson(param.getSceneCode(),1);
|
|
|
+ channel.basicAck(deliveryTag, false);
|
|
|
+ }
|
|
|
+ log.info("场景计算结束,队列名:{},id:{}", queueNameService.getQueueName(), messageId);
|
|
|
+
|
|
|
+
|
|
|
+ }catch (Exception e){
|
|
|
+ if (StrUtil.isNotEmpty(sceneCode)){
|
|
|
+ updateOssStatusJson(sceneCode,0);
|
|
|
+ }
|
|
|
+ channel.basicAck(deliveryTag, false);
|
|
|
+ log.error("场景sceneQueue报错{}",e.getMessage());
|
|
|
+ e.printStackTrace();
|
|
|
+ }finally {
|
|
|
+ //计算完毕,将当前系统构建状态改为false
|
|
|
+ redisUtil.delete(modelingKey);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private void sendEndMq(SceneQueueDTO param) {
|
|
|
+ RelicsSceneInitQueueDTO relicsSceneInitQueueDTO = new RelicsSceneInitQueueDTO();
|
|
|
+ relicsSceneInitQueueDTO.setSceneCode(param.getSceneCode());
|
|
|
+ relicsSceneInitQueueDTO.setLocation(param.getLocation());
|
|
|
+ relicsSceneInitQueueDTO.setAlgorithmTime(param.getAlgorithmTime());
|
|
|
+ relicsSceneInitQueueDTO.setCreateTime(param.getCreateTime());
|
|
|
+ relicsSceneInitQueueDTO.setPhoneNum(param.getPhoneNum());
|
|
|
+ relicsSceneInitQueueDTO.setUserId(param.getUserId());
|
|
|
+ relicsSceneInitQueueDTO.setSnCode(param.getSnCode());
|
|
|
+ relicsSceneInitQueueDTO.setStatus(param.getStatus());
|
|
|
+ relicsSceneInitQueueDTO.setSceneName(param.getSceneName());
|
|
|
+ relicsSceneInitQueueDTO.setShootCount(param.getShootCount());
|
|
|
+ relicsSceneInitQueueDTO.setSceneSource(param.getSceneSource());
|
|
|
+ relicsSceneInitQueueDTO.setPayStatus(param.getPayStatus());
|
|
|
+ rabbitMqProducerUtil.sendByWorkQueue(relicsInitQueue, relicsSceneInitQueueDTO);
|
|
|
+ }
|
|
|
+ private void updateOssStatusJson(String sceneCode, int status) throws Exception {
|
|
|
+ //修改OSS,status状态 scene_view_data/场景码/data/status.json
|
|
|
+ String statusJson = "scene_view_data/"+sceneCode+"/data/status.json";
|
|
|
+ Boolean exist=ossUtil.doesObjectExist("4dkankan",statusJson);
|
|
|
+ if (exist){
|
|
|
+ String fileContent = ossUtil.getFileContent("4dkankan", statusJson);
|
|
|
+ log.info("statusJson存在: {}",statusJson);
|
|
|
+ JSONObject statusJsonObj = JSONObject.parseObject(fileContent);
|
|
|
+ statusJsonObj.put("status",status);
|
|
|
+ ossUtil.uploadFileBytes("4dkankan",statusJson,statusJsonObj.toJSONString().getBytes(StandardCharsets.UTF_8));
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void initData(WorkAddDto workAddDto, WorkEntity entity){
|
|
|
+ workNavigationSettingService.removeByWorkId(entity.getId());
|
|
|
+ //添加默认分组
|
|
|
+ WorkNavigationDTO defaultGroup = WorkNavigationDTO.builder().parentId(0L).name("一级分组").sort(0).build();
|
|
|
+ defaultGroup.setWorkId(entity.getId());
|
|
|
+ WorkNavigationVo workNavigationVo = workNavigationSettingService.addGroup(defaultGroup);
|
|
|
+ List<WorkNavigationEntity> workNavigationEntities = BeanUtil.copyToList(workAddDto.getSceneDTOList(), WorkNavigationEntity.class);
|
|
|
+ AtomicInteger sort = new AtomicInteger(0);
|
|
|
+ workNavigationEntities.stream().forEach(v->{
|
|
|
+ v.setParentId(workNavigationVo.getId());
|
|
|
+ v.setWorkId(entity.getId());
|
|
|
+ v.setSort(sort.getAndAdd(1));
|
|
|
+ });
|
|
|
+ workNavigationService.saveBatch(workNavigationEntities);
|
|
|
+
|
|
|
+ //初始化遮罩数据
|
|
|
+ this.initMaskData(workNavigationEntities,entity.getId());
|
|
|
+
|
|
|
+ //初始化自定义按钮
|
|
|
+ this.initCustomButton(entity.getId());
|
|
|
+
|
|
|
+ //初始化开场动画设置
|
|
|
+ this.initOpenAnimation(entity.getId());
|
|
|
+
|
|
|
+ //初始化开场封面
|
|
|
+ this.initWorkCoverType(entity.getId());
|
|
|
+
|
|
|
+ //初始化自定义logo
|
|
|
+ this.initWorkLogo(entity.getId());
|
|
|
+
|
|
|
+ //初始化开场提示
|
|
|
+ this.initWorkOpeningTip(entity.getId());
|
|
|
+
|
|
|
+ }
|
|
|
+ public void initWorkOpeningTip(String workId){
|
|
|
+ WorkOpeningTipEntity entity = workOpeningTipService.getByWorkId(workId);
|
|
|
+ if (ObjectUtil.isNull(entity)){
|
|
|
+ entity = new WorkOpeningTipEntity();
|
|
|
+ entity.setWorkId(workId);
|
|
|
+ entity.setIsRemind(1);
|
|
|
+ entity.setRemindTime(1);
|
|
|
+ workOpeningTipService.saveOrUpdate(entity);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ public void initWorkLogo(String workId){
|
|
|
+ WorkLogoEntity entity = workLogoService.getByWorkId(workId);
|
|
|
+ if (ObjectUtil.isNull(entity)){
|
|
|
+ entity = new WorkLogoEntity();
|
|
|
+ entity.setWorkId(workId);
|
|
|
+ entity.setIsLogo(1);
|
|
|
+ workLogoService.saveOrUpdate(entity);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public void initOpenAnimation(String workId){
|
|
|
+ WorkOpeningAnimationEntity entity = workOpeningAnimationService.getByWorkId(workId);
|
|
|
+ if (ObjectUtil.isNull(entity)){
|
|
|
+ entity = new WorkOpeningAnimationEntity();
|
|
|
+ entity.setIsShowOpeningAnimation(true);
|
|
|
+ entity.setOpeningAnimationType(1);
|
|
|
+ entity.setWorkId(workId);
|
|
|
+ workOpeningAnimationService.save(entity);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ public void initWorkCoverType(String workId){
|
|
|
+ WorkCoverTypeEntity entity = workCoverTypeService.getByWorkId(workId);
|
|
|
+ if (ObjectUtil.isNull(entity)){
|
|
|
+ entity = new WorkCoverTypeEntity();
|
|
|
+ entity.setWorkId(workId);
|
|
|
+ entity.setCoverSelect("img");
|
|
|
+ entity.setCoverPcLoc("center");
|
|
|
+ entity.setCoverMoLoc("center");
|
|
|
+ entity.setCoverImgBac("colorFill");
|
|
|
+ entity.setImgColorSelec("#000000");
|
|
|
+ entity.setCoverImageInWay(1);
|
|
|
+ workCoverTypeService.saveOrUpdate(entity);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private void initCustomButton(String workId){
|
|
|
+ List<WorkCustomButtonEntity> workCustomButtonEntities = workCustomButtonService.listByWorkId(workId);
|
|
|
+ if (CollUtil.isEmpty(workCustomButtonEntities)){
|
|
|
+ WorkCustomButtonEntity phoneButton = new WorkCustomButtonEntity();
|
|
|
+ phoneButton.setWorkId(workId);
|
|
|
+ phoneButton.setIsShow(0);
|
|
|
+ phoneButton.setName("电话");
|
|
|
+ phoneButton.setType("phone");
|
|
|
+ phoneButton.setOpenMethod("_self");
|
|
|
+ phoneButton.setCreateTime(new Date());
|
|
|
+
|
|
|
+ WorkCustomButtonEntity linkButton = BeanUtil.toBean(phoneButton, WorkCustomButtonEntity.class);
|
|
|
+ linkButton.setName("链接");
|
|
|
+ workCustomButtonService.saveBatch(Arrays.asList(phoneButton, linkButton));
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void initMaskData(List<WorkNavigationEntity> workNavigations, String workId){
|
|
|
+ List<WorkCustomMaskEntity> workCustomMaskEntities = workCustomMaskService.listByWorkId(workId);
|
|
|
+ if(CollUtil.isEmpty(workCustomMaskEntities)) {
|
|
|
+ List<WorkCustomMaskEntity> list = new ArrayList<>();
|
|
|
+ workNavigations.stream().forEach(v -> {
|
|
|
+ WorkCustomMaskEntity sky = new WorkCustomMaskEntity();
|
|
|
+ sky.setWorkId(v.getWorkId());
|
|
|
+ sky.setNavigationId(v.getId());
|
|
|
+ sky.setIsShow(true);
|
|
|
+ sky.setType("sky");
|
|
|
+ sky.setAntidistorted(true);
|
|
|
+ sky.setScale(1D);
|
|
|
+ list.add(sky);
|
|
|
+
|
|
|
+ WorkCustomMaskEntity earth = BeanUtil.toBean(sky, WorkCustomMaskEntity.class);
|
|
|
+ earth.setType("earth");
|
|
|
+ earth.setIsShow(false);
|
|
|
+ list.add(earth);
|
|
|
+ });
|
|
|
+ if (CollUtil.isNotEmpty(list)) {
|
|
|
+ workCustomMaskService.saveBatch(list);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private ScenePanoEntity doSlice(String traceId, String item, String num, String workId, String imgName, String uuid, String id){
|
|
|
+ ScenePanoEntity entity=scenePanoService.findByWorkIdAndName(workId,imgName);
|
|
|
+ String sceneCode ="";
|
|
|
+ String newName = "";
|
|
|
+ String filePath = "";
|
|
|
+ if (ObjectUtil.isEmpty(entity)) {
|
|
|
+ //未生成
|
|
|
+ sceneCode = RandomUtils.getSceneCode("fd720_");
|
|
|
+ newName = sceneCode + ".jpg";
|
|
|
+ filePath = configConstant.serverBasePath + sceneCode+ "/" + newName;
|
|
|
+ ossUtil.downloadFile("4dkankan",item,filePath );
|
|
|
+
|
|
|
+ entity = new ScenePanoEntity();
|
|
|
+ entity.setFilePath(filePath);
|
|
|
+ entity.setFileName(FileUtil.getName(filePath));
|
|
|
+ entity.setSceneCode(sceneCode);
|
|
|
+ entity.setNum(num);
|
|
|
+ entity.setOssPath(item);
|
|
|
+ entity.setName(imgName);
|
|
|
+ entity.setWorkId(workId);
|
|
|
+ entity.setVisid(id);
|
|
|
+ entity.setUuid(uuid);
|
|
|
+ long size = FileUtil.size(new File(filePath));
|
|
|
+ size = size / 1024;
|
|
|
+ log.info("fileSize: " + size);
|
|
|
+ entity.setFileSize(size + "");
|
|
|
+
|
|
|
+ scenePanoService.save(entity);
|
|
|
+ }else {
|
|
|
+ entity.setStatus(0);
|
|
|
+
|
|
|
+ filePath = entity.getFilePath();
|
|
|
+ sceneCode = entity.getSceneCode();
|
|
|
+ boolean exist = FileUtil.exist(filePath);
|
|
|
+ if (exist){
|
|
|
+ FileUtil.del(filePath);
|
|
|
+ }
|
|
|
+ if (filePath.endsWith(".jpg")){
|
|
|
+ String parent = FileUtil.getParent(filePath, 1);
|
|
|
+ FileUtil.del(parent);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ log.info("生成过,重新下载");
|
|
|
+ ossUtil.downloadFile("4dkankan",item,filePath );
|
|
|
+ log.info("下载完成重新切图");
|
|
|
+ long size = FileUtil.size(new File(filePath));
|
|
|
+ size = size / 1024;
|
|
|
+ log.info("fileSize: " + size);
|
|
|
+ entity.setFileSize(size + "");
|
|
|
+ scenePanoService.updateById(entity);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ log.info("切图流程开始 : " + filePath);
|
|
|
+ long start = System.currentTimeMillis();
|
|
|
+
|
|
|
+ String cmd = CmdConstant.PANO_KRPANO + filePath;
|
|
|
+ // 超时处理机制
|
|
|
+ final ExecutorService exec = Executors.newFixedThreadPool(1);
|
|
|
+ Callable<String> call = new Callable<String>() {
|
|
|
+ @Override
|
|
|
+ public String call() throws Exception {
|
|
|
+ MDC.put("TRACE_ID", traceId);
|
|
|
+ CmdUtils.callLine(cmd, 200);
|
|
|
+ long end = System.currentTimeMillis();
|
|
|
+ log.info("切图完成耗时: {} s" ,(end-start)/1000);
|
|
|
+ return "执行完成";
|
|
|
+ }
|
|
|
+ };
|
|
|
+ // 超时回调
|
|
|
+ Future<String> future = exec.submit(call);
|
|
|
+ try {
|
|
|
+ String obj = future.get(20, TimeUnit.MINUTES); //任务处理超时时间设为 3分钟
|
|
|
+ entity.setStatus(3);
|
|
|
+ String tourXmlScene = this.getTourXmlScene(sceneCode);
|
|
|
+ entity.setTour(tourXmlScene);
|
|
|
+ // 上传切图
|
|
|
+ this.uploadOss(sceneCode);
|
|
|
+ String ossUrl = ossUtil.calculateUrl("") + configConstant.ossBasePath + sceneCode+"/vtour/panos/"+sceneCode+".tiles/thumb.jpg";
|
|
|
+ log.info("切图预览图ossUrl: {}",ossUrl);
|
|
|
+ entity.setIcon(ossUrl);
|
|
|
+ log.info("任务成功返回: " + obj);
|
|
|
+
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ entity.setStatus(2);
|
|
|
+ StringWriter trace=new StringWriter();
|
|
|
+ log.error(trace.toString());
|
|
|
+ log.error("异常了 InterruptedException");
|
|
|
+ } catch (ExecutionException | BaseRuntimeException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ StringWriter trace=new StringWriter();
|
|
|
+ e.printStackTrace(new PrintWriter(trace));
|
|
|
+ log.error("超时了 1");
|
|
|
+ // 异常日志要打印,不然不会出现在日志文件中,只会出现在控制台
|
|
|
+ log.error(trace.toString());
|
|
|
+ entity.setStatus(2);
|
|
|
+ future.cancel(true);
|
|
|
+ } catch (TimeoutException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ StringWriter trace=new StringWriter();
|
|
|
+ e.printStackTrace(new PrintWriter(trace));
|
|
|
+ log.error("超时了 2");
|
|
|
+ log.error(trace.toString());
|
|
|
+ entity.setStatus(2);
|
|
|
+ future.cancel(true);
|
|
|
+ } finally {
|
|
|
+ scenePanoService.updateById(entity);
|
|
|
+ log.info("切图流程, 更新数据库完成 : ");
|
|
|
+ }
|
|
|
+ log.info("切图流程结束 : ");
|
|
|
+ return entity;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 更新 tour.xml
|
|
|
+ * @param id
|
|
|
+ */
|
|
|
+ private void saveTour(String id) {
|
|
|
+ List<ScenePanoEntity> list = scenePanoService.findByWorkId(id);
|
|
|
+ // 读取tour.xml模板
|
|
|
+ String baseTour = getBaseTour();
|
|
|
+ StringBuilder builder = new StringBuilder();
|
|
|
+ builder.append(baseTour).append("\r\n");
|
|
|
+ for (ScenePanoEntity entity : list) {
|
|
|
+ String tour = entity.getTour();
|
|
|
+ builder.append(tour).append("\r\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加结束标签
|
|
|
+ builder.append("</krpano>");
|
|
|
+
|
|
|
+ String tourPath = configConstant.serverBasePath + id + "/tour.xml";
|
|
|
+ FileUtil.writeUtf8String(builder.toString(), tourPath);
|
|
|
+ log.info("作品tour.xml写入完成");
|
|
|
+
|
|
|
+ String ossKeyPath = configConstant.ossBasePath + id + "/tour.xml";
|
|
|
+ ossUtil.uploadFile( ossKeyPath,tourPath);
|
|
|
+ log.info("tour.xml上传完成 : {}", ossKeyPath);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getBaseTour(){
|
|
|
+ String baseTourPath = configConstant.serverBasePath + "baseData/tour.xml";
|
|
|
+ String s = FileUtil.readString(baseTourPath, "utf-8");
|
|
|
+ // 结束标签置空, 方便操作
|
|
|
+ s = s.replace("</krpano>", "");
|
|
|
+ return s;
|
|
|
+ }
|
|
|
+ private void uploadOss(String sceneCode) {
|
|
|
+ long start = System.currentTimeMillis();
|
|
|
+ String filePath = "/mnt/720yun_fd_manage_data/" + sceneCode;
|
|
|
+ String ossKey = "720yun_fd_manage/" + sceneCode;
|
|
|
+ fileAndOssUtil.uploadBySh(filePath, ossKey);
|
|
|
+ long end = System.currentTimeMillis();
|
|
|
+ log.info("切图上传完成, 耗时:{} s" , (end-start)/1000 );
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取切图后的tour.xml
|
|
|
+ private String getTourXmlScene(String code) {
|
|
|
+ log.info("处理tour.xml");
|
|
|
+ String tourPath = configConstant.serverBasePath + code + "/vtour/tour.xml";
|
|
|
+ log.info("tourPath: {}", tourPath);
|
|
|
+ BaseRuntimeException.isTrue(!FileUtil.isFile(tourPath), null, code + "_tour.xml文件不存在");
|
|
|
+
|
|
|
+ String tour = FileUtil.readUtf8String(tourPath);
|
|
|
+ tour = this.extractSceneTag(tour);
|
|
|
+ String trim = StrUtil.trim(tour);
|
|
|
+ // log.info("trim: {}", trim);
|
|
|
+ BaseRuntimeException.isTrue(StrUtil.isAllBlank(trim), null, code + "_tour.xml文件不存在");
|
|
|
+
|
|
|
+ // 2022-09-15 加入相对路径
|
|
|
+ String basePath = "%CURRENTXML%../" + code + "/vtour/panos/";
|
|
|
+ trim = trim.replaceAll("panos/", basePath);
|
|
|
+
|
|
|
+ return trim;
|
|
|
+ }
|
|
|
+ public static String extractSceneTag(String xmlString) {
|
|
|
+ Pattern pattern = Pattern.compile("<scene.*?</scene>", Pattern.DOTALL);
|
|
|
+ Matcher matcher = pattern.matcher(xmlString);
|
|
|
+
|
|
|
+ if (matcher.find()) {
|
|
|
+ return matcher.group();
|
|
|
+ }
|
|
|
+
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+}
|