dengsixing 8 months ago
parent
commit
c6468f8a75

+ 41 - 0
src/main/java/com/fdkankan/common/constant/OperationType.java

@@ -0,0 +1,41 @@
+package com.fdkankan.common.constant;
+
+/**
+ * 操作类型枚举
+ */
+public enum OperationType {
+
+    DELETE(-1, "删除"),
+    UPDATE(0, "修改"),
+    ADD(1, "新增"),
+    ADDORUPDATE(2, "新增或修改");
+
+    private Integer code;
+    private String message;
+
+    private OperationType(Integer code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public Integer code() {
+        return code;
+    }
+
+    public String message() {
+        return message;
+    }
+
+    public static OperationType get(Integer code){
+        OperationType[] values = OperationType.values();
+        Integer enumValue = null;
+        for(OperationType eachValue : values){
+            enumValue = eachValue.code();
+            if(enumValue.equals(code)){
+                return eachValue;
+            }
+        }
+        return null;
+    }
+
+}

+ 71 - 0
src/main/java/com/fdkankan/common/util/ComputerUtil.java

@@ -0,0 +1,71 @@
+package com.fdkankan.common.util;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.common.constant.ErrorCode;
+import com.fdkankan.common.exception.BusinessException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+
+/**
+ * 生成场景和计算场景
+ * Created by Hb_zzZ on 2019/5/8.
+ */
+public class ComputerUtil {
+
+    private static Logger log = LoggerFactory.getLogger(ComputerUtil.class.getName());
+
+    /**
+     * 循环检测算法是否计算成功
+     * @param uploadJsonPath uploadjson路径
+     * @param maxCheckTimes 循环次数
+     * @param waitTime 每次检测间隔时间,毫秒
+     * @return boolean
+     * @throws Exception
+     */
+    public static boolean checkComputeCompleted(String uploadJsonPath, int maxCheckTimes, long waitTime) throws Exception{
+        int checkTimes = 1;
+        boolean exist = false;
+        do {
+            if(new File(uploadJsonPath).exists()){
+                exist = true;
+                break;
+            }
+            Thread.sleep(waitTime);
+            ++checkTimes;
+        }while (checkTimes <= maxCheckTimes);
+
+        return exist;
+    }
+
+    /**
+     * 获取计算完需要上传的文件数组
+     * @param uploadJsonPath uploadjson路径
+     * @param maxCheckTimes 校验upload.json文件是否存在循环次数
+     * @param waitTime 每次检测间隔时间,毫秒
+     * @return boolean
+     * @throws Exception
+     */
+    public static JSONArray getUploadArray(String uploadJsonPath, int maxCheckTimes, long waitTime) throws Exception{
+        boolean buildCompeleted = ComputerUtil.checkComputeCompleted(uploadJsonPath, maxCheckTimes, waitTime);
+        if(!buildCompeleted){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_7013);
+        }
+        String uploadData = FileUtil.readUtf8String(uploadJsonPath);
+        JSONObject uploadJson;
+        JSONArray array = null;
+        if(StrUtil.isNotEmpty(uploadData)) {
+            uploadJson = JSONObject.parseObject(uploadData);
+            array = uploadJson.getJSONArray("upload");
+        }
+        if(CollUtil.isEmpty(array)){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_7013);
+        }
+        return array;
+    }
+}

+ 39 - 0
src/main/java/com/fdkankan/common/util/FileUtils.java

@@ -0,0 +1,39 @@
+package com.fdkankan.common.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FileUtils {
+
+    private static Logger log = LoggerFactory.getLogger(FileUtils.class);
+
+
+    /**
+     * 判断文件大小处于限制内
+     *
+     * @param fileLen 文件长度
+     * @param fileSize 限制大小
+     * @param fileUnit 限制的单位(B,K,M,G)
+     * @return
+     */
+    public static boolean checkFileSizeIsLimit(Long fileLen, double fileSize, String fileUnit) {
+//        long len = file.length();
+        double fileSizeCom = 0;
+        if ("B".equals(fileUnit.toUpperCase())) {
+            fileSizeCom = (double) fileLen;
+        } else if ("K".equals(fileUnit.toUpperCase())) {
+            fileSizeCom = (double) fileLen / 1024;
+        } else if ("M".equals(fileUnit.toUpperCase())) {
+            fileSizeCom = (double) fileLen / (1024*1024);
+        } else if ("G".equals(fileUnit.toUpperCase())) {
+            fileSizeCom = (double) fileLen / (1024*1024*1024);
+        }
+        if (fileSizeCom > fileSize) {
+            return false;
+        }
+        return true;
+
+    }
+
+
+}

+ 142 - 0
src/main/java/com/fdkankan/common/util/OBJToGLBUtil.java

@@ -0,0 +1,142 @@
+package com.fdkankan.common.util;
+
+import cn.hutool.core.img.ImgUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.file.FileReader;
+import cn.hutool.core.util.RuntimeUtil;
+import com.fdkankan.common.constant.ErrorCode;
+import com.fdkankan.common.exception.BusinessException;
+import lombok.extern.slf4j.Slf4j;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Locale;
+
+@Slf4j
+public class OBJToGLBUtil {
+
+    /**
+     *
+     * @param objPath obj文件的目录
+     * @param glbPath glb文件的最对路径
+     */
+    public static void objToGlb(String objPath, String glbPath) {
+        OBJToGLBUtil.checkObj(objPath);
+        objPath = OBJToGLBUtil.getObj(objPath);
+        String command = "obj2gltf -i " + objPath + " -o " + glbPath;
+        log.info("开始执行obj转换gbl命令-{}", command);
+        Process exec = RuntimeUtil.exec(command);
+        log.info("结束执行obj转换gbl命令-{}", command);
+    }
+
+    static String getObj(String objPath) {
+        List<File> files = FileUtil.loopFiles(objPath);
+        if (objPath.toLowerCase(Locale.ROOT).contains(".obj")) {
+            return objPath;
+        }
+        for (File file2 : files) {
+            if (file2.isDirectory()) {
+                continue;
+            }
+            if (FileUtil.extName(file2.getName()).toLowerCase(Locale.ROOT).equals("obj")) {
+                return file2.getAbsolutePath();
+            }
+        }
+        return "";
+    }
+
+
+    private static boolean checkObj(String objPath) {
+        if (objPath.contains(".obg")) {
+            objPath = FileUtil.file(objPath).getParent();
+        }
+        File file1 = new File(objPath);
+        File[] files = file1.listFiles();
+        if (files == null || files.length <= 0) {
+            throw new BusinessException(ErrorCode.FAILURE_CODE_7014);
+        }
+        File mtlFile = null;
+        File objFile = null;
+        for (File file2 : files) {
+            if (file2.getName().endsWith(".obj")) {
+//                if (StringUtils.isChinese(file2.getName())) {
+//                    throw new ServiceException(HttpStatus.e7008.getMsg(), HttpStatus.e7008.getCode());
+//                }
+                objFile = file2;
+            }
+            if (file2.getName().endsWith(".mtl")) {
+//                if (StringUtils.isChinese(file2.getName())) {
+//                    throw new ServiceException(HttpStatus.e7008.getMsg(), HttpStatus.e7008.getCode());
+//                }
+                mtlFile = file2;
+            }
+            if (FileUtil.getType(file2).equals("jpg") || FileUtil.getType(file2).equals("png")) {
+                BufferedImage read = ImgUtil.read(file2);
+                int widthImg = read.getWidth();
+                int heightImg = read.getHeight();
+                if (widthImg > 2048 && heightImg > 2048) {
+                    OBJToGLBUtil.log.info("尺寸大2k,执行压缩");
+                    ImgUtil.scale(file2,
+                            file2,
+                            2048, 2048, null);
+                }
+            }
+        }
+        if (mtlFile == null || objFile == null) {
+            throw new BusinessException(ErrorCode.FAILURE_CODE_5059);
+        }
+        return OBJToGLBUtil.checkMtl(file1, mtlFile);
+    }
+
+    private static boolean checkMtl(File allFile, File file) {
+        if (!file.getName().endsWith(".mtl")) {
+            return false;
+        }
+        LinkedHashSet<String> imgName = new LinkedHashSet<>();
+        if (allFile == null || allFile.length() <= 0) {
+            return false;
+        }
+        File[] files = allFile.listFiles();
+        if (files == null || files.length <= 0) {
+            return false;
+        }
+        for (File listFile : files) {
+            String modelName = listFile.getName();
+            imgName.add(modelName);
+        }
+        LinkedHashSet<String> imgMtl = OBJToGLBUtil.readMtlFile(file.getPath());
+        for (String mtlName : imgMtl) {
+            if (!imgName.contains(mtlName)) {
+                throw new BusinessException(ErrorCode.FAILURE_CODE_5065);
+            }
+        }
+        return true;
+    }
+
+    private static LinkedHashSet<String> readMtlFile(String mtlPath) {
+        LinkedHashSet<String> imgName = new LinkedHashSet<>();
+        FileReader fileReader = new FileReader(mtlPath);
+        try {
+            List<String> lines = fileReader.readLines();
+            for (String line : lines) {
+                String[] tempsa = line.split("[ ]+");
+                if (tempsa[0].trim().equals("map_Ka")) {
+                    imgName.add(tempsa[1]);
+                }
+                if (tempsa[0].trim().equals("map_Kd")) {
+                    imgName.add(tempsa[1]);
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return imgName;
+    }
+
+
+    public static void main(String[] args) {
+        System.out.println(OBJToGLBUtil.checkObj("F:\\test\\新建文件夹\\police模型"));
+    }
+}

+ 44 - 51
src/main/java/com/fdkankan/scene/controller/SceneEditController.java

@@ -37,8 +37,8 @@ public class SceneEditController extends BaseController{
 //    private IDownloadTourVideoService downloadTourVideoService;
 //    @Autowired
 //    private ISurveillanceService surveillanceService;
-//    @Autowired
-//    private IBoxModelService boxModelService;
+    @Autowired
+    private IBoxModelService boxModelService;
 //    @Autowired
 //    private IScenePlusService scenePlusService;
 //    @Autowired
@@ -778,55 +778,48 @@ public class SceneEditController extends BaseController{
 //        return ResultData.ok(surveillanceService.listSurveillance(param.getNum()));
 //    }
 //
-//    /**
-//     * <p>
-//     上传空间模型
-//     * </p>
-//     * @author dengsixing
-//     * @date 2022/10/19
-//     * @param num
-//     * @param sid
-//     * @param file
-//     * @return com.fdkankan.common.response.ResultData
-//     **/
-//    @CheckPermit
-//    @PostMapping("/model/box/upload")
-//    public ResultData uploadBoxModel(
-//        @RequestParam(value = "num") String num,
-//        @RequestParam(value = "sid") String sid,
-//        @RequestParam(value = "file") MultipartFile file) throws Exception {
-//        return boxModelService.uploadBoxModel(num, sid, file);
-//    }
-//
-//    /**
-//     * <p>
-//     保存空间模型
-//     * </p>
-//     * @author dengsixing
-//     * @date 2022/10/19
-//     * @param param
-//     * @return com.fdkankan.common.response.ResultData
-//     **/
-//    @CheckPermit
-//    @PostMapping("/model/box/save")
-//    public ResultData saveBoxModel(@RequestBody @Validated BaseJsonDataParamVO param) throws Exception {
-//        return boxModelService.saveBoxModel(param);
-//    }
-//
-//    /**
-//     * <p>
-//     删除空间模型
-//     * </p>
-//     * @author dengsixing
-//     * @date 2022/10/19
-//     * @param param
-//     * @return com.fdkankan.common.response.ResultData
-//     **/
-//    @CheckPermit
-//    @PostMapping("/model/box/delete")
-//    public ResultData delBoxModel(@RequestBody @Validated DeleteSidParamVO param) throws Exception {
-//        return boxModelService.deleteBoxModel(param);
-//    }
+    /**
+     * <p>
+     上传空间模型
+     * </p>
+     * @author dengsixing
+     * @param num
+     * @param sid
+     * @param file
+     * @return com.fdkankan.common.response.ResultData
+     **/
+    @PostMapping("/model/box/upload")
+    public ResultData uploadBoxModel(
+        @RequestParam(value = "num") String num,
+        @RequestParam(value = "sid") String sid,
+        @RequestParam(value = "file") MultipartFile file) throws Exception {
+        return boxModelService.uploadBoxModel(num, this.getSubgroup(), sid, file);
+    }
+
+    /**
+     * <p>
+     保存空间模型
+     * </p>
+     * @author dengsixing
+     * @return com.fdkankan.common.response.ResultData
+     **/
+    @PostMapping("/model/box/save")
+    public ResultData saveBoxModel(@RequestBody @Validated BaseJsonDataParamVO param) throws Exception {
+        param.setSubgroup(this.getSubgroup());
+        return boxModelService.saveBoxModel(param);
+    }
+
+    /**
+     * <p>
+     删除空间模型
+     * </p>
+     * @author dengsixing
+     * @return com.fdkankan.common.response.ResultData
+     **/
+    @PostMapping("/model/box/delete")
+    public ResultData delBoxModel(@RequestBody @Validated DeleteSidParamVO param) throws Exception {
+        return boxModelService.deleteBoxModel(param);
+    }
 //
 //    /**
 //     * 上传二维码和分享的logo

+ 32 - 0
src/main/java/com/fdkankan/scene/service/IBoxModelService.java

@@ -0,0 +1,32 @@
+package com.fdkankan.scene.service;
+
+import com.fdkankan.scene.bean.ResultData;
+import com.fdkankan.scene.vo.BaseJsonDataParamVO;
+import com.fdkankan.scene.vo.DeleteSidParamVO;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * <p>
+ * TODO
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/10/19
+ **/
+public interface IBoxModelService {
+
+    /**
+     * 上传并转换obj
+     * @param num 场景码
+     * @param sid sid
+     * @param file obj压缩包
+     * @return ResutData
+     * @throws Exception
+     */
+    ResultData uploadBoxModel(String num, Integer subgroup, String sid, MultipartFile file) throws Exception;
+
+    ResultData saveBoxModel(BaseJsonDataParamVO param) throws Exception;
+
+    ResultData deleteBoxModel(DeleteSidParamVO param) throws Exception;
+
+}

+ 249 - 0
src/main/java/com/fdkankan/scene/service/impl/BoxModelServiceImpl.java

@@ -0,0 +1,249 @@
+package com.fdkankan.scene.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.core.util.ZipUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.fdkankan.common.constant.ConstantFilePath;
+import com.fdkankan.common.constant.ErrorCode;
+import com.fdkankan.common.constant.OperationType;
+import com.fdkankan.common.constant.ServerCode;
+import com.fdkankan.common.constant.UploadFilePath;
+import com.fdkankan.common.exception.BusinessException;
+import com.fdkankan.common.util.ComputerUtil;
+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.scene.bean.BoxModelBean;
+import com.fdkankan.scene.bean.ResultData;
+import com.fdkankan.scene.entity.Scene;
+import com.fdkankan.scene.entity.SceneEditInfo;
+import com.fdkankan.scene.entity.ScenePlus;
+import com.fdkankan.scene.entity.ScenePlusExt;
+import com.fdkankan.scene.service.FYunFileService;
+import com.fdkankan.scene.service.IBoxModelService;
+import com.fdkankan.scene.service.ISceneEditInfoService;
+import com.fdkankan.scene.service.IScenePlusExtService;
+import com.fdkankan.scene.service.IScenePlusService;
+import com.fdkankan.scene.service.SceneEditInfoService;
+import com.fdkankan.scene.service.SceneService;
+import com.fdkankan.scene.vo.BaseJsonDataParamVO;
+import com.fdkankan.scene.vo.DeleteSidParamVO;
+import com.fdkankan.web.response.ResultData;
+import com.google.common.collect.Lists;
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+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;
+
+/**
+ * <p>
+ * TODO
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/10/19
+ **/
+@Slf4j
+@Service
+public class BoxModelServiceImpl implements IBoxModelService {
+
+    @Resource
+    FYunFileService fYunFileService;
+    @Autowired
+    private SceneService scenePlusService;
+    @Autowired
+    private SceneEditInfoService sceneEditInfoService;
+
+    @Override
+    public ResultData uploadBoxModel(String num, Integer subgroup, String sid, MultipartFile file) throws Exception {
+
+        Scene scenePlus = scenePlusService.getByNum(num, subgroup);
+        if(Objects.isNull(scenePlus)){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
+        }
+
+        if(!file.getOriginalFilename().endsWith(".zip")){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_7015);
+        }
+
+        if(!FileUtils.checkFileSizeIsLimit(file.getSize(), 5, "M")){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_7023, "5M");
+        }
+        String path = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + "boxModel/" + sid + "/";
+        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);
+
+        //校验是否包含目录,如果包含目录提示错误
+        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, 3, 2000)){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_7013);
+        }
+
+        //上传glb
+        fYunFileService.uploadFile(num, scenePlus.getSubgroup(), glbPath, String.format(UploadFilePath.USER_VIEW_PATH, num) + "boxModels/" + sid + ".glb");
+
+        return ResultData.ok(sid + ".glb");
+    }
+
+    public static void main(String[] args) {
+        ZipUtil.unzip("F:\\test\\新建文件夹\\police模型\\police模型.zip","F:\\test\\新建文件夹\\police模型\\maps");
+    }
+
+    @Override
+    public ResultData saveBoxModel(BaseJsonDataParamVO param) throws Exception {
+
+        JSONObject data = param.getData();
+        String sid = data.getString("sid");
+        if(StrUtil.isEmpty(sid)){
+            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
+        }
+        Scene scenePlus = scenePlusService.getByNum(param.getNum(), param.getSubgroup());
+        if(Objects.isNull(scenePlus))
+            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
+
+        SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
+
+        //生成boxVideos数据
+        String boxPhotos = this.createBoxModels(param.getNum(), param.getSubgroup(), sid, data, sceneEditInfo, OperationType.ADDORUPDATE.code());
+
+        //更新数据库
+        this.updateBoxModels(sceneEditInfo, boxPhotos);
+
+        return ResultData.ok();
+    }
+
+    @Override
+    public ResultData deleteBoxModel(DeleteSidParamVO param) throws Exception {
+
+        Scene scenePlus = scenePlusService.getByNum(param.getNum(), param.getSubgroup());
+        if(Objects.isNull(scenePlus))
+            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
+
+        SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
+
+        //根据sid移除json
+        String boxModels = this.createBoxModels(param.getNum(), param.getSubgroup(), param.getSid(), null, sceneEditInfo, OperationType.DELETE.code());
+
+        //写数据库
+        this.updateBoxModels(sceneEditInfo, boxModels);
+
+        return ResultData.ok();
+    }
+
+    private void updateBoxModels(SceneEditInfo sceneEditInfo, String boxModels){
+        sceneEditInfoService.update(new LambdaUpdateWrapper<SceneEditInfo>()
+            .set(SceneEditInfo::getBoxModels, boxModels)
+            .setSql("version = version + 1")
+            .eq(SceneEditInfo::getId, sceneEditInfo.getId()));
+    }
+
+    private String createBoxModels(String num, Integer subgroup, String sid, JSONObject data, SceneEditInfo sceneEditInfo, int type){
+
+        String boxModels = null;
+        if(sceneEditInfo != null){
+            boxModels = sceneEditInfo.getBoxModels();
+        }
+        JSONArray boxModelsJson = null;
+        if (StrUtil.isNotEmpty(boxModels)) {
+            boxModelsJson = JSONArray.parseArray(boxModels);
+        }else {
+            boxModelsJson = new JSONArray();
+        }
+
+        String result = null;
+        //删除
+        if(type == OperationType.DELETE.code()){
+            Set<String> deleteFile = new HashSet<>();
+            if(boxModelsJson.size() == 0)
+                return null;
+            for(int i=0;i<boxModelsJson.size();++i){
+                JSONObject ele = boxModelsJson.getJSONObject(i);
+                if(ele.getString("sid").equals(sid)){
+                    boxModelsJson.remove(i);
+                    deleteFile.add(String.format(UploadFilePath.USER_VIEW_PATH, num) + sid + ".glb");
+                }
+            }
+            //删除资源文件
+            if(CollUtil.isNotEmpty(deleteFile))
+                deleteFile.stream().forEach(key -> {
+                    try {
+                        fYunFileService.deleteFile(num, subgroup, key);
+                    } catch (Exception e) {
+                        log.warn("oss删除文件失败,key:{}", key);
+                    }
+                });
+        }else{
+            //更新
+            boolean exist = false;
+            for(int i=0;i<boxModelsJson.size();++i){
+                JSONObject ele = boxModelsJson.getJSONObject(i);
+                if(ele.getString("sid").equals(sid)){
+                    data.put("createTime", ele.getLong("createTime"));
+                    boxModelsJson.set(i, data);
+                    exist = true;
+                }
+            }
+            //新增
+            if(!exist){
+                data.put("createTime", Calendar.getInstance().getTimeInMillis());
+                boxModelsJson.add(data);
+            }
+
+        }
+        if(boxModelsJson.size() != 0){
+
+            List<BoxModelBean> list = Lists.newArrayList();
+            for (Object o : boxModelsJson) {
+                JSONObject jsonObject = (JSONObject)o;
+                list.add(BoxModelBean.builder().createTime(jsonObject.getLong("createTime")).boxModel(jsonObject).build());
+            }
+            //按创建时间倒叙排序
+            list.sort(Comparator.comparingLong(BoxModelBean::getCreateTime).reversed());
+
+            // list转JSONArray
+            JSONArray array = new JSONArray();
+            list.stream().forEach(bean->{
+                array.add(bean.getBoxModel());
+            });
+
+            result = array.toJSONString();
+        }
+
+        return result;
+    }
+}

+ 22 - 0
src/main/java/com/fdkankan/scene/vo/BaseJsonDataParamVO.java

@@ -0,0 +1,22 @@
+package com.fdkankan.scene.vo;
+
+import com.alibaba.fastjson.JSONObject;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import lombok.Data;
+
+/**
+ * <p>
+ * 通用data类型参数类
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/2/10
+ **/
+@Data
+public class BaseJsonDataParamVO extends BaseSceneParamVO{
+
+    @NotNull(message = "数据不能为空")
+    private JSONObject data;
+
+}

+ 20 - 0
src/main/java/com/fdkankan/scene/vo/DeleteSidParamVO.java

@@ -0,0 +1,20 @@
+package com.fdkankan.scene.vo;
+
+import javax.validation.constraints.NotBlank;
+import lombok.Data;
+
+/**
+ * <p>
+ * TODO
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/2/18
+ **/
+@Data
+public class DeleteSidParamVO extends BaseSceneParamVO{
+
+    @NotBlank(message = "sid不能为空")
+    private String sid;
+
+}