|
|
@@ -1,15 +1,54 @@
|
|
|
package com.fdkankan.scene.service.impl;
|
|
|
|
|
|
import cn.hutool.core.bean.BeanUtil;
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.exceptions.ExceptionUtil;
|
|
|
+import cn.hutool.core.io.FileUtil;
|
|
|
+import cn.hutool.core.lang.UUID;
|
|
|
+import cn.hutool.core.util.CharsetUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import cn.hutool.core.util.ZipUtil;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
import com.fdkankan.common.constant.CommonStatus;
|
|
|
import com.fdkankan.common.constant.CommonSuccessStatus;
|
|
|
+import com.fdkankan.common.constant.ErrorCode;
|
|
|
+import com.fdkankan.common.exception.BusinessException;
|
|
|
+import com.fdkankan.common.util.DateExtUtil;
|
|
|
+import com.fdkankan.common.util.OBJToGLBUtil;
|
|
|
+import com.fdkankan.fyun.face.FYunFileServiceInterface;
|
|
|
+import com.fdkankan.model.constants.ConstantFilePath;
|
|
|
+import com.fdkankan.model.constants.UploadFilePath;
|
|
|
+import com.fdkankan.model.utils.ComputerUtil;
|
|
|
+import com.fdkankan.rabbitmq.util.RabbitMqProducer;
|
|
|
+import com.fdkankan.scene.constant.BoxModelType;
|
|
|
+import com.fdkankan.scene.constant.NjsErrorCode;
|
|
|
+import com.fdkankan.scene.dto.NjsBoxModelDTO;
|
|
|
import com.fdkankan.scene.dto.SaveBoxModelDTO;
|
|
|
import com.fdkankan.scene.entity.NjsSceneBoxModel;
|
|
|
+import com.fdkankan.scene.entity.SceneEditInfo;
|
|
|
+import com.fdkankan.scene.entity.ScenePlus;
|
|
|
import com.fdkankan.scene.mapper.INjsSceneBoxModelMapper;
|
|
|
import com.fdkankan.scene.service.INjsSceneBoxModelService;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import com.fdkankan.scene.service.ISceneEditInfoService;
|
|
|
+import com.fdkankan.scene.service.IScenePlusService;
|
|
|
+import com.fdkankan.scene.vo.BaseSceneParamVO;
|
|
|
+import com.fdkankan.scene.vo.BathUpdateNjsBoxModelParamVO;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.io.File;
|
|
|
+import java.io.IOException;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.time.Instant;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
/**
|
|
|
* <p>
|
|
|
* NJS-模型编辑器数据表 服务实现类
|
|
|
@@ -18,21 +57,207 @@ import org.springframework.stereotype.Service;
|
|
|
* @author
|
|
|
* @since 2026-01-09
|
|
|
*/
|
|
|
+@Slf4j
|
|
|
@Service
|
|
|
public class NjsSceneBoxModelServiceImpl extends ServiceImpl<INjsSceneBoxModelMapper, NjsSceneBoxModel> implements INjsSceneBoxModelService {
|
|
|
|
|
|
- @Override
|
|
|
- public void saveBoxModel(SaveBoxModelDTO dto) {
|
|
|
+ @Resource
|
|
|
+ private RabbitMqProducer mqProducer;
|
|
|
+ @Resource
|
|
|
+ private FYunFileServiceInterface fYunFileService;
|
|
|
+ @Autowired
|
|
|
+ private IScenePlusService scenePlusService;
|
|
|
+ @Autowired
|
|
|
+ private ISceneEditInfoService sceneEditInfoService;
|
|
|
|
|
|
- NjsSceneBoxModel bean = BeanUtil.toBean(dto, NjsSceneBoxModel.class);
|
|
|
- if(dto.getModelType().equals("upload")){
|
|
|
+// private static Set<Long> TRANSFER_IDS = new HashSet<>();
|
|
|
+//
|
|
|
+// private static ExecutorService executor = Executors.newFixedThreadPool(10);
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 每隔十分钟拉取一次压缩包
|
|
|
+// */
|
|
|
+// @Scheduled(fixedDelay = 60*1000, initialDelay = 1000)
|
|
|
+// public void transferGlb() {
|
|
|
+// log.info("推送模型转换开始");
|
|
|
+// LambdaQueryWrapper<NjsSceneBoxModel> wrapper = new LambdaQueryWrapper<>();
|
|
|
+// wrapper.in(NjsSceneBoxModel::getStatus, CommonSuccessStatus.WAITING.code());
|
|
|
+// int limit = 10;
|
|
|
+// if(!TRANSFER_IDS.isEmpty()){
|
|
|
+// wrapper.notIn(NjsSceneBoxModel::getId, TRANSFER_IDS);
|
|
|
+// limit = limit - TRANSFER_IDS.size();
|
|
|
+// }
|
|
|
+// wrapper.orderByAsc(NjsSceneBoxModel::getCreateTime);
|
|
|
+// wrapper.last("limit " + limit);
|
|
|
+// List<NjsSceneBoxModel> list = this.list(wrapper);
|
|
|
+// if(list.isEmpty()){
|
|
|
+// log.info("无数据推送模型转换");
|
|
|
+// return;
|
|
|
+// }
|
|
|
+//
|
|
|
+// List<CompletableFuture<Void>> futures = list.stream()
|
|
|
+// .map(item -> CompletableFuture.runAsync(
|
|
|
+// () -> (item), executor
|
|
|
+// ))
|
|
|
+// .toList();
|
|
|
+//
|
|
|
+// CompletableFuture.allOf(
|
|
|
+// futures.toArray(new CompletableFuture[0])
|
|
|
+// ).join();
|
|
|
+//
|
|
|
+// executor.shutdown();
|
|
|
+//
|
|
|
+// log.info("推送模型转换结束");
|
|
|
+// }
|
|
|
+//
|
|
|
+// private void transferGlb
|
|
|
|
|
|
+ @Override
|
|
|
+ public void saveBoxModel(SaveBoxModelDTO dto) {
|
|
|
+ NjsSceneBoxModel bean = null;
|
|
|
+ if(dto.getId() != null){
|
|
|
+ bean = this.getById(dto.getId());
|
|
|
+ if(bean == null){
|
|
|
+ throw new BusinessException(NjsErrorCode.NOT_EXISTS.code(), NjsErrorCode.NOT_EXISTS.message());
|
|
|
+ }
|
|
|
+ if(bean.getStatus().equals(CommonSuccessStatus.WAITING.code())){
|
|
|
+ throw new BusinessException(NjsErrorCode.TRANSFING.code(), NjsErrorCode.TRANSFING.message());
|
|
|
+ }
|
|
|
}else{
|
|
|
- bean.setLoaded(CommonStatus.YES.compareTo());
|
|
|
+ bean = BeanUtil.toBean(dto, NjsSceneBoxModel.class);
|
|
|
+ }
|
|
|
+ if(dto.getModelType().equals("draw")){
|
|
|
+ bean.setLoaded(CommonStatus.YES.code().intValue());
|
|
|
bean.setStatus(CommonSuccessStatus.SUCCESS.code());
|
|
|
}
|
|
|
this.save(bean);
|
|
|
|
|
|
+ //如果是上转本地obj的方式,需要将obj转glb
|
|
|
+ if(BoxModelType.UPLOAD.code().equals(dto.getModelType())){
|
|
|
+ JSONObject content = new JSONObject();
|
|
|
+ content.put("id", bean.getId());
|
|
|
+ mqProducer.sendByWorkQueue("njs-obj-to-glb", content);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<NjsBoxModelDTO> listNjsBoxModel(BaseSceneParamVO param) {
|
|
|
+ List<NjsSceneBoxModel> list = lambdaQuery().eq(NjsSceneBoxModel::getNum, param.getNum()).list();
|
|
|
+ ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
|
|
|
+ SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
|
|
|
+ List<NjsBoxModelDTO> results = new ArrayList<>();
|
|
|
+ if(CollUtil.isNotEmpty(list)){
|
|
|
+ List<NjsBoxModelDTO> njsBoxModelDTOS = BeanUtil.copyToList(list, NjsBoxModelDTO.class);
|
|
|
+ njsBoxModelDTOS.stream().forEach(v->v.setSourceType("model"));
|
|
|
+ results.addAll(njsBoxModelDTOS);
|
|
|
+ }
|
|
|
+ if(StrUtil.isNotEmpty(sceneEditInfo.getBoxModels())){
|
|
|
+ JSONArray boxModels = JSON.parseArray(sceneEditInfo.getBoxModels());
|
|
|
+ List<NjsBoxModelDTO> collect = boxModels.stream().map(m -> {
|
|
|
+ JSONObject boxModel = JSON.parseObject(JSON.toJSONString(m));
|
|
|
+ Long createTime = boxModel.getLong("createTime");
|
|
|
+ return NjsBoxModelDTO.builder()
|
|
|
+ .modelName(boxModel.getString("zipName"))
|
|
|
+ .sourceType("mesh")
|
|
|
+ .createTime(createTime == null ? null : DateExtUtil.date(createTime))
|
|
|
+ .build();
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ results.addAll(collect);
|
|
|
+ }
|
|
|
+ if(CollUtil.isEmpty(list)){
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return results.stream()
|
|
|
+ .sorted(
|
|
|
+ Comparator.comparing(
|
|
|
+ NjsBoxModelDTO::getCreateTime,
|
|
|
+ Comparator.nullsLast(Date::compareTo)
|
|
|
+ ).reversed()
|
|
|
+ ).collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void batchDisplay(BathUpdateNjsBoxModelParamVO param) {
|
|
|
+ LambdaUpdateWrapper<NjsSceneBoxModel> wrapper = new LambdaUpdateWrapper();
|
|
|
+ wrapper.eq(NjsSceneBoxModel::getNum, param.getNum());
|
|
|
+ wrapper.in(NjsSceneBoxModel::getId, param.getIdList());
|
|
|
+ if(param.getDisplay() != null){
|
|
|
+ wrapper.set(NjsSceneBoxModel::getDisplay, param.getDisplay());
|
|
|
+ }
|
|
|
+ if(param.getDisplaySize() != null){
|
|
|
+ wrapper.set(NjsSceneBoxModel::getDisplaySize, param.getDisplaySize());
|
|
|
+ }
|
|
|
+ this.update(wrapper);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void batchDelete(BathUpdateNjsBoxModelParamVO param) throws IOException {
|
|
|
+ List<NjsSceneBoxModel> list = lambdaQuery().eq(NjsSceneBoxModel::getNum, param.getNum()).in(NjsSceneBoxModel::getId, param.getIdList()).list();
|
|
|
+ if(list.isEmpty()){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ lambdaUpdate().eq(NjsSceneBoxModel::getNum, param.getNum()).in(NjsSceneBoxModel::getId, param.getIdList()).remove();
|
|
|
+ //删除文件
|
|
|
+ for (NjsSceneBoxModel njsSceneBoxModel : list) {
|
|
|
+ String key = String.format(UploadFilePath.USER_EDIT_PATH, njsSceneBoxModel.getNum()) + "njsBoxModel" + File.separator + njsSceneBoxModel.getSid() + ".glb";
|
|
|
+ if(fYunFileService.fileExist(key)){
|
|
|
+ fYunFileService.deleteFile(key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void objToGlb(JSONObject param) throws Exception {
|
|
|
+ Long id = param.getLong("id");
|
|
|
+ NjsSceneBoxModel njsSceneBoxModel = this.getById(id);
|
|
|
+ if(njsSceneBoxModel == null){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String uuid = UUID.randomUUID().toString();
|
|
|
+ String origKey = njsSceneBoxModel.getOrigKey();
|
|
|
+ String workDir = String.format(ConstantFilePath.SCENE_USER_PATH_V4, njsSceneBoxModel.getNum()) + "objToGlb" + File.separator + uuid + File.separator;
|
|
|
+ try {
|
|
|
+ String zipPath = workDir + FileUtil.getName(origKey);
|
|
|
+ fYunFileService.downloadFile(origKey, zipPath);
|
|
|
+ //解压
|
|
|
+ ZipUtil.unzip(zipPath, workDir, CharsetUtil.CHARSET_GBK);
|
|
|
+ //转glb
|
|
|
+ String glbPath = workDir + uuid + ".glb";
|
|
|
+ OBJToGLBUtil.objToGlb(workDir, glbPath);
|
|
|
+ //上传glb
|
|
|
+ if(!ComputerUtil.checkComputeCompleted(glbPath, 5, 200)){
|
|
|
+ throw new RuntimeException("转glb失败");
|
|
|
+ }
|
|
|
+ String key = String.format(UploadFilePath.USER_EDIT_PATH, njsSceneBoxModel.getNum()) + "njsBoxModel" + File.separator + njsSceneBoxModel.getSid() + ".glb";
|
|
|
+ fYunFileService.uploadFile(glbPath, key);
|
|
|
+ njsSceneBoxModel.setStatus(CommonSuccessStatus.SUCCESS.code());
|
|
|
+ }catch (Exception e){
|
|
|
+ log.error("模型编辑器-模型转换失败, num:{}, sid:{}", njsSceneBoxModel.getNum(), njsSceneBoxModel.getSid(), e);
|
|
|
+ njsSceneBoxModel.setReason(ExceptionUtil.stacktraceToString(e, 3000));
|
|
|
+ njsSceneBoxModel.setStatus(CommonSuccessStatus.FAIL.code());
|
|
|
+ }finally{
|
|
|
+ this.updateById(njsSceneBoxModel);
|
|
|
+ //删除文件
|
|
|
+ fYunFileService.deleteFile(origKey);
|
|
|
+ FileUtil.del(workDir);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void publicNjsSceneBoxModel(String num) throws IOException {
|
|
|
+ List<NjsSceneBoxModel> list = lambdaQuery().eq(NjsSceneBoxModel::getNum, num)
|
|
|
+ .eq(NjsSceneBoxModel::getStatus, CommonSuccessStatus.SUCCESS.code()).list();
|
|
|
+ String njsBoxModelKey = String.format(UploadFilePath.USER_EDIT_PATH, num) + "njsBoxModels.json";
|
|
|
+ if(list.isEmpty() && fYunFileService.fileExist(njsBoxModelKey)){
|
|
|
+ fYunFileService.deleteFile(njsBoxModelKey);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ fYunFileService.uploadFile(JSON.toJSONString(list).getBytes(StandardCharsets.UTF_8), njsBoxModelKey);
|
|
|
+ }
|
|
|
|
|
|
+ public static void main(String[] args) {
|
|
|
+ System.out.println(Instant.EPOCH.toEpochMilli());
|
|
|
}
|
|
|
}
|