ScenePlusServiceImpl.java 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. package com.fdkankan.scene.service.impl;
  2. import cn.hutool.core.bean.BeanUtil;
  3. import cn.hutool.core.collection.CollUtil;
  4. import cn.hutool.core.date.DateField;
  5. import cn.hutool.core.date.DateUtil;
  6. import cn.hutool.core.io.FileUtil;
  7. import cn.hutool.core.thread.ThreadUtil;
  8. import cn.hutool.core.util.StrUtil;
  9. import cn.hutool.extra.qrcode.QrCodeUtil;
  10. import cn.hutool.extra.qrcode.QrConfig;
  11. import com.alibaba.fastjson.JSON;
  12. import com.alibaba.fastjson.JSONArray;
  13. import com.alibaba.fastjson.JSONObject;
  14. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  15. import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
  16. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  17. import com.fdkankan.common.constant.*;
  18. import com.fdkankan.common.exception.BusinessException;
  19. import com.fdkankan.common.util.FileUtils;
  20. import com.fdkankan.model.constants.ConstantFilePath;
  21. import com.fdkankan.model.constants.UploadFilePath;
  22. import com.fdkankan.model.utils.FloorPlanUserUtil;
  23. import com.fdkankan.scene.bean.SceneBean;
  24. import com.fdkankan.scene.constant.UserEditDataType;
  25. import com.fdkankan.scene.entity.SceneEditInfoExt;
  26. import com.fdkankan.scene.entity.ScenePro;
  27. import com.fdkankan.scene.service.ISceneEditInfoExtService;
  28. import com.fdkankan.scene.service.ISceneProService;
  29. import com.fdkankan.web.response.ResultData;
  30. import com.fdkankan.redis.constant.RedisKey;
  31. import com.fdkankan.redis.constant.RedisLockKey;
  32. import com.fdkankan.redis.util.RedisLockUtil;
  33. import com.fdkankan.redis.util.RedisUtil;
  34. import com.fdkankan.scene.bean.LaserSceneBean;
  35. import com.fdkankan.scene.bean.SceneJsonBean;
  36. import com.fdkankan.scene.config.FdkkLaserConfig;
  37. import com.fdkankan.scene.entity.*;
  38. import com.fdkankan.scene.mapper.IScenePlusMapper;
  39. import com.fdkankan.scene.oss.OssUtil;
  40. import com.fdkankan.scene.service.*;
  41. import com.fdkankan.scene.vo.SceneCheckKeyParamVO;
  42. import com.fdkankan.scene.vo.SceneDataDownloadVO;
  43. import com.fdkankan.scene.vo.SceneEditControlsVO;
  44. import com.fdkankan.web.response.ResultData;
  45. import java.io.File;
  46. import java.io.IOException;
  47. import java.nio.file.FileSystemException;
  48. import java.util.*;
  49. import lombok.extern.slf4j.Slf4j;
  50. import org.apache.commons.lang3.StringUtils;
  51. import org.springframework.beans.factory.annotation.Autowired;
  52. import org.springframework.beans.factory.annotation.Value;
  53. import org.springframework.stereotype.Service;
  54. import org.springframework.web.multipart.MultipartFile;
  55. import java.io.File;
  56. import java.nio.charset.StandardCharsets;
  57. import java.util.List;
  58. import java.util.Objects;
  59. import java.util.UUID;
  60. import java.util.stream.Collectors;
  61. import java.util.stream.Stream;
  62. /**
  63. * <p>
  64. * 场景主表 服务实现类
  65. * </p>
  66. *
  67. * @author
  68. * @since 2022-03-16
  69. */
  70. @Slf4j
  71. @Service
  72. public class ScenePlusServiceImpl extends ServiceImpl<IScenePlusMapper, ScenePlus> implements IScenePlusService {
  73. @Value("${main.url}")
  74. private String mainUrl;
  75. @Value("${scene.pro.new.url}")
  76. private String sceneProNewUrl;
  77. @Autowired
  78. private IScenePlusExtService scenePlusExtService;
  79. @Autowired
  80. private IScenePlusService scenePlusService;
  81. @Autowired
  82. private ISceneEditInfoService sceneEditInfoService;
  83. @Autowired
  84. private ISceneDataDownloadService sceneDataDownloadService;
  85. @Autowired
  86. private RedisUtil redisUtil;
  87. @Autowired
  88. private RedisLockUtil redisLockUtil;
  89. @Autowired
  90. private ISceneEditInfoExtService sceneEditInfoExtService;
  91. @Autowired
  92. private ISceneEditControlsService sceneEditControlsService;
  93. @Autowired
  94. private OssUtil ossUtil;
  95. @Autowired
  96. FdkkLaserConfig fdkkLaserConfig;
  97. @Autowired
  98. private ISceneProService sceneProService;
  99. @Autowired
  100. private ISceneDelLogService sceneDelLogService;
  101. @Autowired
  102. private ICommonService commonService;
  103. @Autowired
  104. private FloorplanAiService floorplanAiService;
  105. @Autowired
  106. private IAiService aiService;
  107. @Override
  108. public ScenePlus getScenePlusByNum(String num) {
  109. return this.getOne(new LambdaQueryWrapper<ScenePlus>().eq(ScenePlus::getNum, num));
  110. }
  111. @Override
  112. public ResultData checkKey(SceneCheckKeyParamVO param) throws Exception {
  113. ScenePlus scenePlus = scenePlusService.getOne(new LambdaQueryWrapper<ScenePlus>()
  114. .eq(ScenePlus::getNum, param.getNum())
  115. .eq(ScenePlus::getPayStatus, PayStatus.PAY.code()));
  116. if (Objects.isNull(scenePlus)) {
  117. throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
  118. }
  119. SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
  120. if (Objects.isNull(sceneEditInfo)) {
  121. throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
  122. }
  123. if(!param.getPassword().equals(sceneEditInfo.getScenePassword())){
  124. throw new BusinessException(ErrorCode.FAILURE_CODE_5021);
  125. }
  126. return ResultData.ok();
  127. }
  128. @Override
  129. public ResultData updateScenePlusUserIdByCameraId(List<Long> cameraIdList, Long userId) {
  130. LambdaUpdateWrapper<ScenePlus> updateWrapper = new LambdaUpdateWrapper<ScenePlus>()
  131. .set(ScenePlus::getUserId, userId).in(ScenePlus::getCameraId, cameraIdList);
  132. this.update(updateWrapper);
  133. return ResultData.ok();
  134. }
  135. @Override
  136. public ResultData moveScene(List<String> numList, Long cameraId, Long userId) {
  137. LambdaUpdateWrapper<ScenePlus> updateWrapper =
  138. new LambdaUpdateWrapper<ScenePlus>()
  139. .set(ScenePlus::getUserId, userId)
  140. .set(ScenePlus::getCameraId, cameraId)
  141. .in(ScenePlus::getNum, numList);
  142. this.update(updateWrapper);
  143. return ResultData.ok();
  144. }
  145. @Override
  146. public ResultData downLoadZSData(String num) throws Exception {
  147. if(StrUtil.isEmpty(num)){
  148. throw new BusinessException(ErrorCode.FAILURE_CODE_3001);
  149. }
  150. String version = "v4";
  151. ScenePlus scenePlus = this.getScenePlusByNum(num);
  152. ScenePro scenePro = null;
  153. if(Objects.isNull(scenePlus)){
  154. scenePro = sceneProService.getByNum(num);
  155. version = "v3";
  156. if(Objects.isNull(scenePro)){
  157. throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
  158. }
  159. }
  160. SceneDataDownload sceneDataDownload = sceneDataDownloadService.findBySceneNum(num);
  161. if(sceneDataDownload == null){
  162. throw new BusinessException(ErrorCode.FAILURE_CODE_5025);
  163. }
  164. SceneDataDownloadVO sceneDataDownloadVO = BeanUtil.copyProperties(sceneDataDownload, SceneDataDownloadVO.class);
  165. sceneDataDownloadVO.setVersion(version);
  166. return ResultData.ok(sceneDataDownloadVO);
  167. }
  168. @Override
  169. public ScenePlus checkSceneAvail(String num) {
  170. ScenePlus scenePlus = this.getScenePlusByNum(num);
  171. if(Objects.isNull(scenePlus)){
  172. throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
  173. }
  174. if(!SceneStatus.SUCCESS.code().equals(scenePlus.getSceneStatus())
  175. && !SceneStatus.NO_DISPLAY.code().equals(scenePlus.getSceneStatus())){
  176. throw new BusinessException(ErrorCode.FAILURE_CODE_5033);
  177. }
  178. if(!PayStatus.PAY.code().equals(scenePlus.getPayStatus())){
  179. throw new BusinessException(ErrorCode.FAILURE_CODE_5034);
  180. }
  181. return scenePlus;
  182. }
  183. @Override
  184. public ResultData updateViewCount(String sceneNum) {
  185. String key = RedisKey.SCENE_VISIT_CNT;
  186. if(!redisUtil.hHasKey(key, sceneNum)){
  187. String lockKey = String.format(RedisLockKey.LOCK_SCENE_VISIT_CNT, sceneNum);
  188. String lockVal = cn.hutool.core.lang.UUID.randomUUID().toString();
  189. boolean lock = redisLockUtil.lock(lockKey, lockVal, RedisKey.EXPIRE_TIME_10_MINUTE);
  190. if(!lock){
  191. return ResultData.ok();
  192. }
  193. try {
  194. String cnt = redisUtil.hget(key, sceneNum);
  195. if(StrUtil.isEmpty(cnt)){
  196. //标记是否找到了场景,如果找到就不往下找
  197. Integer viewCount = null;
  198. ScenePlus scenePlus = scenePlusService.getScenePlusByNum(sceneNum);
  199. ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
  200. viewCount = scenePlusExt.getViewCount();
  201. redisUtil.hset(key, sceneNum, Objects.isNull(viewCount) ? "0" : String.valueOf(viewCount));
  202. }
  203. }finally {
  204. redisLockUtil.unlockLua(lockKey, lockVal);
  205. }
  206. }
  207. redisUtil.hincr(key, sceneNum, 1);
  208. return ResultData.ok();
  209. }
  210. @Override
  211. public ResultData uploadShareLogo(String num, MultipartFile file) throws Exception {
  212. ScenePlus scenePlus = this.getScenePlusByNum(num);
  213. if (Objects.isNull(scenePlus)) {
  214. return ResultData.error(ErrorCode.FAILURE_CODE_5005);
  215. }
  216. ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
  217. SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByScenePlusId(scenePlus.getId());
  218. String bucket = scenePlusExt.getYunFileBucket();
  219. String fileName = file.getOriginalFilename();
  220. String extName = fileName.substring(fileName.lastIndexOf("."));
  221. File newFile = File.createTempFile(UUID.randomUUID().toString() ,extName);
  222. file.transferTo(newFile);
  223. String logoPath = newFile.getPath();
  224. String outPathZh = ConstantFilePath.BASE_PATH + File.separator + "sceneQRcode/"+num+".png";
  225. String outPathEn = ConstantFilePath.BASE_PATH + File.separator + "sceneQRcode/"+num+"_en.png";
  226. String webSize = mainUrl + "/" + sceneProNewUrl + num;
  227. QrCodeUtil.generate(webSize, QrConfig.create().setImg(logoPath).setWidth(1024).setHeight(1024), FileUtil.file(outPathZh));
  228. QrCodeUtil.generate(webSize + "&lang=en", QrConfig.create().setImg(logoPath).setWidth(1024).setHeight(1024), FileUtil.file(outPathEn));
  229. //上传logo图片
  230. String ossLogoPath = String.format(UploadFilePath.DOWNLOADS_QRCODE, num) + "shareLogo" + extName;
  231. ossUtil.uploadFile(bucket, ossLogoPath, logoPath, false);
  232. //上传二维码
  233. ossUtil.uploadFile(bucket, String.format(UploadFilePath.DOWNLOADS_QRCODE, num) + num + ".png", outPathZh, false);
  234. ossUtil.uploadFile(bucket,String.format(UploadFilePath.DOWNLOADS_QRCODE, num) + num + "_en.png", outPathEn, false);
  235. sceneEditInfoExt.setShareLogoImg(ossLogoPath);
  236. sceneEditInfoExtService.updateById(sceneEditInfoExt);
  237. FileUtil.del(newFile);
  238. FileUtil.del(new File(outPathEn));
  239. FileUtil.del(new File(outPathZh));
  240. return ResultData.ok();
  241. }
  242. /**
  243. * <p>
  244. * 初始化场景数据
  245. * </p>
  246. * @author dengsixing
  247. * @date 2022/8/22
  248. * @param num 场景码
  249. * @param title 场景标题
  250. * @param des 场景描述
  251. * @param sceneSource 场景来源:相机拍摄10以内表示,1表示八目,2双目,3转台,4 激光 其他来源10以上,11:一键换装,12:123看房,13文通虚拟场景
  252. * @param dataSource 场景计算数据目录
  253. * @param sceneScheme 方案:1-双目,2-转台,3-六目,4-八目,10-获取4k图,11-获取2k,12-获取1k
  254. * @param sceneResolution 分辨率(2k,4k)
  255. * @param sceneFrom 场景来源,lite:双目lite相机,pro:八目相机,minion:双面转台相机,laser:激光相机,virtual:虚拟场景,sketch:图片建模场景
  256. * @return com.fdkankan.web.response.ResultData
  257. **/
  258. @Override
  259. public ResultData initScene(String bucket, String num, String title, String des, Integer sceneSource,
  260. String dataSource, Integer sceneScheme, String sceneResolution, String sceneFrom, String mdoelKind, Date algorithmTime,
  261. String orientation) throws Exception {
  262. ScenePlus scenePlus = this.getScenePlusByNum(num);
  263. JSONObject fdageData = getFdageData(dataSource + File.separator + "capture" +File.separator+"data.fdage");
  264. Integer videoVersion = fdageData.getInteger("videoVersion");
  265. int cameraType = 10;//默认看看相机
  266. if(sceneSource == 4 || sceneSource == 5){
  267. cameraType = 14;
  268. }
  269. //生成场景主表
  270. if(Objects.isNull(scenePlus)){
  271. scenePlus = new ScenePlus();
  272. }
  273. scenePlus.setNum(num);
  274. scenePlus.setSceneStatus(SceneStatus.wait.code());
  275. scenePlus.setSceneSource(sceneSource);
  276. scenePlus.setPayStatus(PayStatus.PAY.code());
  277. scenePlus.setSceneType(SceneType.OTHER.code());
  278. scenePlus.setTitle(title);
  279. scenePlus.setDescription("<p>" + fdageData.getString("info") + "</p>");
  280. // scenePlus.setLastEditTime(new Date());
  281. scenePlus.setUpdateTime(new Date());
  282. this.saveOrUpdate(scenePlus);
  283. //生成场景拓展表
  284. ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
  285. if(Objects.isNull(scenePlusExt)){
  286. scenePlusExt = new ScenePlusExt();
  287. }
  288. scenePlusExt.setPlusId(scenePlus.getId());
  289. scenePlusExt.setDataSource(dataSource);
  290. scenePlusExt.setSceneScheme(sceneScheme);
  291. scenePlusExt.setSceneResolution(sceneResolution);
  292. scenePlusExt.setSceneFrom(sceneFrom);
  293. scenePlusExt.setModelKind(mdoelKind);
  294. scenePlusExt.setSceneKind(SceneKind.FACE.code());
  295. scenePlusExt.setYunFileBucket(bucket);
  296. scenePlusExt.setAlgorithmTime(Calendar.getInstance().getTime());
  297. scenePlusExt.setVideos(this.getVideosJson(dataSource, videoVersion, num, cameraType).toJSONString());
  298. scenePlusExt.setAlgorithmTime(algorithmTime);
  299. scenePlusExt.setOrientation(orientation);
  300. scenePlusExtService.saveOrUpdate(scenePlusExt);
  301. if(StrUtil.isEmpty(orientation)){
  302. scenePlusExtService.update(new LambdaUpdateWrapper<ScenePlusExt>().eq(ScenePlusExt::getId, scenePlusExt.getId()).setSql("orientation = null"));
  303. }
  304. //开始场景图ai识别
  305. aiService.detectScenePano(scenePlus, scenePlusExt, dataSource);
  306. scenePlusExtService.saveOrUpdate(scenePlusExt);
  307. //生成编辑主表
  308. String pwd = fdageData.getString("pwd");
  309. SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
  310. if(Objects.isNull(sceneEditInfo)){
  311. sceneEditInfo = new SceneEditInfo();
  312. }else{
  313. sceneEditInfo.setVersion(sceneEditInfo.getVersion() + 1);
  314. }
  315. sceneEditInfo.setScenePlusId(scenePlus.getId());
  316. sceneEditInfo.setTitle(title);
  317. sceneEditInfo.setDescription("<p>" + fdageData.getString("info") + "</p>");
  318. if(StrUtil.isEmpty(sceneEditInfo.getScenePassword())){
  319. sceneEditInfo.setScenePassword(fdageData.getString("pwd"));
  320. }
  321. sceneEditInfoService.saveOrUpdate(sceneEditInfo);
  322. sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
  323. //生成编辑拓展表
  324. SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByEditInfoId(sceneEditInfo.getId());
  325. if(Objects.isNull(sceneEditInfoExt)){
  326. sceneEditInfoExt = new SceneEditInfoExt();
  327. }
  328. sceneEditInfoExt.setScenePlusId(scenePlus.getId());
  329. sceneEditInfoExt.setEditInfoId(sceneEditInfo.getId());
  330. sceneEditInfoExt.setLinks(this.checkIsExistLinks(num) ? CommonStatus.YES.code().intValue() : CommonStatus.NO.code().intValue());
  331. sceneEditInfoExtService.saveOrUpdate(sceneEditInfoExt);
  332. //生成编辑显示控制表
  333. SceneEditControls sceneEditControls = sceneEditControlsService.getBySceneEditId(sceneEditInfo.getId());
  334. if(Objects.isNull(sceneEditControls)){
  335. sceneEditControls = new SceneEditControls();
  336. }
  337. sceneEditControls.setEditInfoId(sceneEditInfo.getId());
  338. sceneEditControls.setShowMap(0);
  339. if(StrUtil.isNotEmpty(pwd)){
  340. sceneEditControls.setShowLock(CommonStatus.YES.code().intValue());
  341. }
  342. sceneEditControlsService.saveOrUpdate(sceneEditControls);
  343. sceneEditControls = sceneEditControlsService.getBySceneEditId(sceneEditInfo.getId());
  344. //平面图ai识别
  345. this.uploadFloorplanAi(num, dataSource, bucket);
  346. LinkedHashMap<Integer, Boolean> detFloorplan = floorplanAiService.detFloorplan(dataSource);
  347. boolean hasFloorplanAi = floorplanAiService.detFloorPlanAi(num, dataSource, detFloorplan, bucket);
  348. if(hasFloorplanAi){
  349. scenePlus.setHasFloorplanAi(CommonStatus.YES.code().intValue());
  350. }else{
  351. scenePlus.setHasFloorplanAi(CommonStatus.NO.code().intValue());
  352. }
  353. scenePlus.setSceneStatus(SceneStatus.SUCCESS.code());
  354. this.saveOrUpdate(scenePlus);
  355. //清除用户编辑业务数据
  356. Set<String> bizs = new HashSet<>();
  357. bizs.add(UserEditDataType.BOX_MODEL.message());
  358. bizs.add(UserEditDataType.FLOORPLAN.message());
  359. commonService.initUserEditData(num, bizs, null);
  360. sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
  361. sceneEditInfoExt = sceneEditInfoExtService.getByEditInfoId(sceneEditInfo.getId());
  362. //生成sceneJson
  363. String sceneJsonPath = String.format(UploadFilePath.DATA_VIEW_PATH+"scene.json", num);
  364. String oldSceneJson = ossUtil.getFileContent(bucket, sceneJsonPath);
  365. SceneJsonBean sceneJson = new SceneJsonBean();
  366. BeanUtil.copyProperties(sceneEditInfoExt, sceneJson);
  367. BeanUtil.copyProperties(sceneEditInfo, sceneJson);
  368. SceneEditControlsVO sceneEditControlsVO = BeanUtil.copyProperties(sceneEditControls, SceneEditControlsVO.class);
  369. sceneJson.setControls(sceneEditControlsVO);
  370. sceneJson.setNum(num);
  371. sceneJson.setCreateTime(scenePlus.getCreateTime());
  372. sceneJson.setSceneResolution(scenePlusExt.getSceneResolution());
  373. sceneJson.setSceneFrom(scenePlusExt.getSceneFrom());
  374. sceneJson.setSceneKind(scenePlusExt.getSceneKind());
  375. sceneJson.setHasRecognition(scenePlusExt.getHasRecognition());
  376. if(StrUtil.isNotEmpty(scenePlusExt.getVideos())){
  377. sceneJson.setVideos(scenePlusExt.getVideos());
  378. }
  379. sceneJson.setModelKind(scenePlusExt.getModelKind());
  380. if(StrUtil.isNotEmpty(oldSceneJson)){
  381. List<JSONObject> mosaicList = JSON.parseObject(oldSceneJson, SceneJsonBean.class).getMosaicList();
  382. sceneJson.setMosaicList(mosaicList);
  383. }
  384. sceneJson.setHasFloorplanAi(scenePlus.getHasFloorplanAi());
  385. //本地写sceneJson文件
  386. ossUtil.uploadFileBytes(bucket, sceneJsonPath, JSON.toJSONString(sceneJson).getBytes(StandardCharsets.UTF_8));
  387. //生成floorplan.json
  388. String floorPlanCardFilePath = dataSource + File.separator + "results/floorplan_cad.json";
  389. if (new File(floorPlanCardFilePath).exists()) {
  390. JSONObject json = FloorPlanUserUtil.createFloorPlanUserJson(floorPlanCardFilePath);
  391. if(!Objects.isNull(json)){
  392. String hourseTypeJsonPath = String.format(UploadFilePath.DATA_VIEW_PATH, num) + "floorplan.json";
  393. ossUtil.uploadFileBytes(bucket, hourseTypeJsonPath, json.toJSONString().getBytes(StandardCharsets.UTF_8));
  394. }
  395. }
  396. redisUtil.del(String.format(RedisKey.SCENE_JSON, num));
  397. return ResultData.ok();
  398. }
  399. public void uploadFloorplanAi(String num, String path, String bucket) throws IOException {
  400. String floorplanPath = path + "/results/floorplan/";
  401. List<File> files = FileUtil.loopFiles(floorplanPath);
  402. String ossPath = String.format(UploadFilePath.DATA_VIEW_PATH, num) + "floorplan/";
  403. if(CollUtil.isNotEmpty(files)){
  404. for (File file : files) {
  405. ossUtil.uploadFile(bucket,file.getAbsolutePath().replace(new File(floorplanPath).getAbsolutePath(), ossPath),file.getAbsolutePath(), false);
  406. // fYunFileService.uploadFile(file.getAbsolutePath(), file.getAbsolutePath().replace(floorplanPath, ossPath));
  407. }
  408. }
  409. }
  410. private boolean checkIsExistLinks(String num){
  411. //查询缓存是否有场景关联数据
  412. String key = String.format(RedisKey.SCENE_LINKPAN_DATA, num);
  413. Map<String, String> allTagsMap = redisUtil.hmget(key);
  414. boolean hashTags = false;
  415. for (Map.Entry<String, String> tagMap : allTagsMap.entrySet()) {
  416. if(StrUtil.isEmpty(tagMap.getValue())){
  417. continue;
  418. }
  419. hashTags = true;
  420. break;
  421. }
  422. return hashTags;
  423. }
  424. private JSONObject getFdageData(String dataFdagePath) {
  425. log.info("dataFdagePath 文件路径 :{}", dataFdagePath);
  426. String data = FileUtils.readFile(dataFdagePath);
  427. //获取data.fdage的内容
  428. JSONObject dataJson = new JSONObject();
  429. if(data!=null){
  430. dataJson = JSONObject.parseObject(data);
  431. }
  432. return dataJson;
  433. }
  434. private JSONObject getVideosJson(String path, Integer videoVersion, String projectNum, int cameraType){
  435. //读取videos_hdr_param.json, 保存点位视频的value
  436. Map<String, Object> videoMap = new HashMap<>();
  437. String videosHdr = FileUtils.readFile(path + File.separator + "results/videos/videos_hdr_param.json");
  438. JSONArray videoArray = null;
  439. if(StringUtils.isNotEmpty(videosHdr)){
  440. videoArray = JSONObject.parseObject(videosHdr).getJSONArray("hdr_param");
  441. }
  442. if(videoArray != null){
  443. for(int i = 0, len = videoArray.size(); i < len; i++) {
  444. videoMap.put(videoArray.getJSONObject(i).getString("name"), videoArray.getJSONObject(i).getString("value"));
  445. if(videoArray.getJSONObject(i).containsKey("fov")){
  446. videoMap.put(videoArray.getJSONObject(i).getString("name") + "_fov", videoArray.getJSONObject(i).getString("fov"));
  447. }
  448. }
  449. }
  450. //获取upload中的video视频名称
  451. String uploadData = FileUtils.readFile(path + File.separator + "results" +File.separator+"upload.json");
  452. JSONObject uploadJson = null;
  453. JSONArray array = null;
  454. if(uploadData!=null) {
  455. uploadJson = JSONObject.parseObject(uploadData);
  456. array = uploadJson.getJSONArray("upload");
  457. }
  458. JSONObject fileJson = null;
  459. String fileName = "";
  460. //计算ts文件的大小,并拼接成json格式
  461. JSONArray jsonArray = new JSONArray();
  462. JSONObject videoJson = null;
  463. JSONObject videosJson = new JSONObject();
  464. long videoSize = 0L;
  465. for(int i = 0, len = array.size(); i < len; i++) {
  466. fileJson = array.getJSONObject(i);
  467. fileName = fileJson.getString("file");
  468. if(fileJson.getIntValue("clazz") == 11 && fileName.contains(".mp4") && !fileName.contains("-ios.mp4")){
  469. videoJson = new JSONObject();
  470. videoJson.put("id", fileName.substring(
  471. 0, fileName.lastIndexOf(".")).replace("videos/", ""));
  472. //如果ts文件存在,就计算ts大小
  473. if(new File(path + File.separator + "results" +File.separator+ fileName.replace(".mp4", ".ts")).exists()){
  474. videoSize = new File(path + File.separator + "results" +File.separator+ fileName.replace(".mp4", ".ts")).length();
  475. videoJson.put("tsSize", videoSize);
  476. }
  477. if(videoMap.containsKey(videoJson.get("id"))){
  478. videoJson.put("value", videoMap.get(videoJson.get("id")));
  479. }
  480. if(videoMap.containsKey(videoJson.get("id") + "_fov")){
  481. videoJson.put("blend_fov", videoMap.get(videoJson.get("id") + "_fov"));
  482. }else {
  483. videoJson.put("blend_fov", 7);
  484. }
  485. jsonArray.add(videoJson);
  486. }
  487. }
  488. videosJson.put("data", jsonArray);
  489. videosJson.put("version", 3);
  490. videosJson.put("upPath", String.format(UploadFilePath.DATA_VIEW_PATH, projectNum) + "Up.txt");
  491. return videosJson;
  492. }
  493. @Override
  494. public ResultData editScene(LaserSceneBean param) {
  495. ScenePlus scenePlus = this.getScenePlusByNum(param.getNum());
  496. if(Objects.isNull(scenePlus))
  497. throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
  498. SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
  499. sceneEditInfo.setTitle(param.getTitle());
  500. if(StrUtil.isEmpty(sceneEditInfo.getEntry())){
  501. sceneEditInfo.setEntry("{}");
  502. }
  503. sceneEditInfoService.updateById(sceneEditInfo);
  504. if (StrUtil.isNotBlank(param.getThumb())){
  505. ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
  506. String bucket = scenePlusExt.getYunFileBucket();
  507. scenePlusExt.setThumb(param.getThumb());
  508. scenePlusExtService.updateById(scenePlusExt);
  509. File sourceFile=FileUtil.file(FdkkLaserConfig.getProfile(bucket)+param.getThumb());
  510. log.info("sourceFile,-{}",sourceFile.getAbsoluteFile());
  511. File targetFile=FileUtil.file(FdkkLaserConfig.getProfile(bucket)+String.format(UploadFilePath.USER_EDIT_PATH, param.getNum())+ File.separator+"thumb-1k.jpg");
  512. log.info("targetFile,-{}",targetFile.getAbsoluteFile());
  513. FileUtils.copyFile(sourceFile,targetFile);
  514. }
  515. return ResultData.ok();
  516. }
  517. @Override
  518. public List<SceneBean> listCleanOrigScene(int cleanOrigMonth) {
  519. Date time = Calendar.getInstance().getTime();
  520. time = DateUtil.beginOfDay(DateUtil.offset(time, DateField.MONTH, -cleanOrigMonth));
  521. return this.baseMapper.selectCleanOrigScene(time);
  522. }
  523. @Override
  524. public List<ScenePlus> getListByNums(List<String> numList) {
  525. LambdaQueryWrapper<ScenePlus> wrapper = new LambdaQueryWrapper<>();
  526. wrapper.in(ScenePlus::getNum,numList);
  527. return this.list(wrapper);
  528. }
  529. @Override
  530. public void deleteByList(List<ScenePlus> plusList, List<String> reserve, boolean reserveSource) throws FileSystemException {
  531. if(CollUtil.isEmpty(plusList)){
  532. return;
  533. }
  534. List<Long> plusIds = plusList.parallelStream().map(ScenePlus::getId).collect(Collectors.toList());
  535. HashMap<Long, ScenePlusExt> plusMap = scenePlusExtService.getByPlusIds(plusIds);
  536. scenePlusService.removeByIds(plusIds);
  537. scenePlusExtService.removeByPlusIds(plusIds);
  538. ThreadUtil.execAsync(() -> {
  539. //删除编辑和展示文件
  540. for (ScenePlus plus : plusList) {
  541. try {
  542. ScenePlusExt scenePlusExt = plusMap.get(plus.getId());
  543. String bucket = scenePlusExt.getYunFileBucket();
  544. ossUtil.deleteObject(bucket, String.format(UploadFilePath.EDIT_PATH, plus.getNum()));
  545. if(CollUtil.isEmpty(reserve)){
  546. ossUtil.deleteObject(bucket, String.format(UploadFilePath.VIEW_PATH, plus.getNum()));
  547. }else{
  548. ossUtil.deleteObject(bucket, String.format(UploadFilePath.USER_VIEW_PATH, plus.getNum()));
  549. List<String> viewFiles = ossUtil.listFiles(bucket, String.format(UploadFilePath.VIEW_PATH, plus.getNum()));
  550. viewFiles.stream().forEach(key -> {
  551. if(!reserve.stream().anyMatch(path -> key.contains(path))){
  552. try {
  553. ossUtil.deleteObject(bucket, key);
  554. } catch (FileSystemException e) {
  555. log.info("删除失败,key:{}", key);
  556. }
  557. }
  558. });
  559. }
  560. } catch (FileSystemException e) {
  561. log.error("删除场景展示数据失败, num:{}", plus.getNum(), e);
  562. }
  563. }
  564. //删除原始资源文件
  565. if(!reserveSource){
  566. for (Long key : plusMap.keySet()) {
  567. ScenePlusExt ext = plusMap.get(key);
  568. if(StrUtil.isNotEmpty(ext.getDataSource()) && ext.getDataSource().length() > 5){
  569. FileUtil.del(ext.getDataSource());
  570. }
  571. }
  572. }
  573. });
  574. }
  575. }