| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- 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.query.LambdaQueryWrapper;
- 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.constant.ServerCode;
- import com.fdkankan.common.exception.BusinessException;
- import com.fdkankan.common.util.DateExtUtil;
- import com.fdkankan.common.util.FileUtils;
- 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.ExportBoxModelDTO;
- 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.entity.ScenePlusExt;
- 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.IScenePlusExtService;
- import com.fdkankan.scene.service.IScenePlusService;
- import com.fdkankan.scene.vo.BaseJsonDataParamVO;
- import com.fdkankan.scene.vo.BaseSceneParamVO;
- import com.fdkankan.scene.vo.BathUpdateNjsBoxModelParamVO;
- import com.fdkankan.scene.vo.DeleteSidListParamVO;
- import com.fdkankan.web.response.ResultData;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import org.springframework.web.multipart.MultipartFile;
- 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-模型编辑器数据表 服务实现类
- * </p>
- *
- * @author
- * @since 2026-01-09
- */
- @Slf4j
- @Service
- public class NjsSceneBoxModelServiceImpl extends ServiceImpl<INjsSceneBoxModelMapper, NjsSceneBoxModel> implements INjsSceneBoxModelService {
- @Resource
- private RabbitMqProducer mqProducer;
- @Resource
- private FYunFileServiceInterface fYunFileService;
- @Autowired
- private IScenePlusService scenePlusService;
- @Autowired
- private ISceneEditInfoService sceneEditInfoService;
- @Autowired
- private IScenePlusExtService scenePlusExtService;
- @Override
- public NjsSceneBoxModel getBySid(String num, String sid) {
- return lambdaQuery().eq(NjsSceneBoxModel::getNum, num).eq(NjsSceneBoxModel::getSid, sid).one();
- }
- @Override
- public void saveBoxModel(BaseJsonDataParamVO dto) {
- JSONObject data = dto.getData();
- String sid = data.getString("sid");
- if(StrUtil.isEmpty(sid)){
- throw new BusinessException(ServerCode.PARAM_REQUIRED, "sid");
- }
- NjsSceneBoxModel bean = this.getBySid(dto.getNum(), sid);
- if(bean == null){
- bean = BeanUtil.toBean(dto, NjsSceneBoxModel.class);
- bean.setSid(sid);
- }else{
- bean.setData(dto.getData());
- bean.setUpdateTime(null);
- }
- this.saveOrUpdate(bean);
- }
- @Override
- public List<JSONObject> listNjsBoxModel(BaseSceneParamVO param) {
- ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
- SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
- List<JSONObject> results = new ArrayList<>();
- if(StrUtil.isNotEmpty(sceneEditInfo.getBoxModels())){
- List<JSONObject> boxModels = JSON.parseArray(
- sceneEditInfo.getBoxModels(),
- JSONObject.class
- );
- boxModels.stream().forEach(v->v.put("sourceType", "mesh"));
- results.addAll(boxModels);
- }
- List<NjsSceneBoxModel> list = lambdaQuery().eq(NjsSceneBoxModel::getNum, param.getNum()).list();
- if(CollUtil.isNotEmpty(list)){
- List<JSONObject> njsBoxModels = list.stream().map(v->{
- JSONObject data = v.getData();
- data.put("createTime", v.getCreateTime().getTime());
- data.put("sourceType", "model");
- return data;
- }).collect(Collectors.toList());
- results.addAll(njsBoxModels);
- }
- if(CollUtil.isEmpty(results)){
- return null;
- }
- results.sort(Comparator.comparing(
- o -> ((JSONObject)o).getLong("createTime"),
- Comparator.nullsLast(Long::compareTo)
- ).reversed());
- return results;
- }
- @Override
- public void batchVisible(BathUpdateNjsBoxModelParamVO param) {
- LambdaQueryWrapper<NjsSceneBoxModel> wrapper = new LambdaQueryWrapper();
- wrapper.eq(NjsSceneBoxModel::getNum, param.getNum());
- wrapper.in(NjsSceneBoxModel::getSid, param.getSidList());
- List<NjsSceneBoxModel> list = this.list(wrapper);
- if(list.isEmpty()){
- return;
- }
- list.stream().forEach(v->{
- JSONObject data = v.getData();
- if(param.getVisible() != null){
- data.put("visible", param.getVisible());
- }
- if(param.getVisibleSize() != null){
- data.put("visibleSize", param.getVisibleSize());
- }
- v.setUpdateTime(null);
- });
- this.updateBatchById(list);
- }
- @Override
- public void batchDelete(BathUpdateNjsBoxModelParamVO param) throws IOException {
- List<NjsSceneBoxModel> list = lambdaQuery().eq(NjsSceneBoxModel::getNum, param.getNum()).in(NjsSceneBoxModel::getSid, param.getSidList()).list();
- if(list.isEmpty()){
- return;
- }
- lambdaUpdate().eq(NjsSceneBoxModel::getNum, param.getNum()).in(NjsSceneBoxModel::getSid, param.getSidList()).remove();
- //删除文件
- for (NjsSceneBoxModel njsSceneBoxModel : list) {
- String ossDir = String.format(UploadFilePath.USER_EDIT_PATH, njsSceneBoxModel.getNum()) + "njsBoxModel" + File.separator + njsSceneBoxModel.getSid();
- String key = ossDir + ".glb";
- if(fYunFileService.fileExist(key)){
- fYunFileService.deleteFile(key);
- }
- if(fYunFileService.fileExist(ossDir)){
- fYunFileService.deleteFolder(ossDir);
- }
- }
- }
- // @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;
- // String srcPath = workDir + "src" + File.separator;
- // try {
- // FileUtil.mkdir(srcPath);
- // String zipPath = workDir + FileUtil.getName(origKey);
- // fYunFileService.downloadFile(origKey, zipPath);
- // //解压
- // ZipUtil.unzip(zipPath, srcPath, CharsetUtil.CHARSET_GBK);
- // //转glb
- // String glbPath = workDir + uuid + ".glb";
- // OBJToGLBUtil.objToGlb(srcPath, glbPath);
- // //上传glb
- // if(!ComputerUtil.checkComputeCompleted(glbPath, 5, 200)){
- // throw new RuntimeException("转glb失败");
- // }
- // String ossDir = String.format(UploadFilePath.USER_EDIT_PATH, njsSceneBoxModel.getNum()) + "njsBoxModel" + File.separator + njsSceneBoxModel.getSid();
- // String key = ossDir + ".glb";
- // //上传结果文件
- // fYunFileService.uploadFile(glbPath, key);
- // njsSceneBoxModel.setGlbKey(key);
- // //上传源文件
- // List<File> files = FileUtil.loopFiles(srcPath);
- // files.stream().forEach(v->{
- // String ossKey = v.getAbsolutePath().replace(srcPath, ossDir + File.separator);
- // fYunFileService.uploadFile(v.getAbsolutePath(), ossKey);
- // });
- // 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).list();
- String njsBoxModelKey = String.format(UploadFilePath.USER_EDIT_PATH, num) + "njsBoxModels.json";
- String njsBoxModelDir = String.format(UploadFilePath.USER_EDIT_PATH, num) + "njsBoxModel";
- if(list.isEmpty()){
- if(fYunFileService.fileExist(njsBoxModelKey)){
- fYunFileService.deleteFile(njsBoxModelKey);
- }
- if(fYunFileService.fileExist(njsBoxModelDir)){
- fYunFileService.deleteFile(njsBoxModelDir);
- }
- return;
- }
- //删除无效文件
- Set<String> prefixList = list.stream().map(v -> njsBoxModelDir + "/" + v.getData().getString("sid")).collect(Collectors.toSet());
- List<String> keyList = fYunFileService.listRemoteFiles(njsBoxModelDir);
- if(!keyList.isEmpty()){
- keyList.removeIf(file ->
- prefixList.stream().anyMatch(file::startsWith)
- );
- if(!keyList.isEmpty()){
- keyList.stream().forEach(key -> {
- try {
- fYunFileService.deleteFile(key);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- });
- }
- }
- List<JSONObject> collect = list.stream().map(v -> v.getData()).collect(Collectors.toList());
- fYunFileService.uploadFile(JSON.toJSONString(collect).getBytes(StandardCharsets.UTF_8), njsBoxModelKey);
- }
- public static void main(String[] args) {
- List<String> prefixes = Arrays.asList(
- "img/",
- "video/2025/",
- "model/mesh/"
- );
- List<String> files = new ArrayList<>(Arrays.asList(
- "img/a.png",
- "img/b.jpg",
- "tmp/c.txt",
- "video/2024/d.mp4",
- "model/mesh/x.obj"
- ));
- files.removeIf(file ->
- prefixes.stream().anyMatch(file::startsWith)
- );
- System.out.println(files);
- }
- @Override
- public ResultData uploadBoxModel(String num, String sid, MultipartFile file) throws Exception {
- if(!file.getOriginalFilename().endsWith(".zip")){
- throw new BusinessException(ErrorCode.FAILURE_CODE_7015);
- }
- if(!FileUtils.checkFileSizeIsLimit(file.getSize(), 100, "M")){
- throw new BusinessException(ErrorCode.FAILURE_CODE_7023, "100M");
- }
- String path = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + "njsBoxModel/" + sid + "/";
- try {
- String zipPath = path + file.getOriginalFilename();
- String srcPath = path + "data/";
- String glbPath = path + sid + ".glb";
- FileUtil.del(path);
- FileUtil.mkParentDirs(zipPath);
- file.transferTo(new File(zipPath));
- //解压
- ZipUtil.unzip(zipPath,srcPath, CharsetUtil.CHARSET_GBK);
- //校验是否包含目录,如果包含目录提示错误
- File srcFile = new File(srcPath);
- Arrays.stream(srcFile.listFiles()).forEach(subFile->{
- if(subFile.isDirectory()){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5065);
- }
- });
- //转glb
- OBJToGLBUtil.objToGlb(srcPath, glbPath);
- if(!ComputerUtil.checkComputeCompleted(glbPath, 10, 2000)){
- throw new BusinessException(ErrorCode.FAILURE_CODE_7013);
- }
- //上传glb
- fYunFileService.uploadFile(glbPath, String.format(UploadFilePath.USER_EDIT_PATH, num) + "njsBoxModel/" + sid + ".glb");
- //上传原始obj相关文件
- String objPath = String.format(UploadFilePath.USER_EDIT_PATH, num) + "njsBoxModel/" + sid + "/";
- //先删除旧的,只需要保留最新的
- fYunFileService.deleteFolder(objPath);
- List<File> files = FileUtil.loopFiles(srcPath);
- files.stream().forEach(v->{
- String ossKey = String.format(UploadFilePath.USER_EDIT_PATH, num) + "njsBoxModel/" + sid + "/" + v.getAbsolutePath().replace(srcPath, "");
- fYunFileService.uploadFile(v.getAbsolutePath(), ossKey);
- });
- return ResultData.ok(sid + ".glb");
- }catch (Exception e){
- log.error("上传三维模型失败", e);
- throw e;
- }finally {
- FileUtil.del(path);
- }
- }
- }
|