dsx пре 2 година
родитељ
комит
a6d238ba00

+ 21 - 0
src/main/java/com/fdkankan/scene/controller/Scene3dNumMatterProController.java

@@ -0,0 +1,21 @@
+package com.fdkankan.scene.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * matter_pro场景码 前端控制器
+ * </p>
+ *
+ * @author 
+ * @since 2022-11-24
+ */
+@RestController
+@RequestMapping("/scene/scene3dNumMatterPro")
+public class Scene3dNumMatterProController {
+
+}
+

+ 53 - 0
src/main/java/com/fdkankan/scene/controller/inner/InnerController.java

@@ -0,0 +1,53 @@
+package com.fdkankan.scene.controller.inner;
+
+import com.fdkankan.scene.service.IInnerApiService;
+import com.fdkankan.web.annotation.CheckInnerApiPermit;
+import com.fdkankan.web.controller.BaseController;
+import com.fdkankan.web.response.ResultData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * <p>
+ * 内部接口控制器
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/8/19
+ **/
+@RestController
+@RequestMapping("/service/scenev3/_inner")
+public class InnerController extends BaseController {
+
+    @Autowired
+    private IInnerApiService innerApiService;
+
+    /**
+     * 上传matterpro数据
+     */
+    @CheckInnerApiPermit
+    @PostMapping("/uploadMatterproData")
+    public ResultData uploadMatterproData(@RequestParam(value = "sceneName",required = false) String sceneName,
+        @RequestParam(value = "userName",required = false) String userName,
+        @RequestParam(value = "floor",required = false) String floor,
+        @RequestParam(value = "sceneKind",defaultValue = "tiles") String sceneKind,
+        @RequestParam(value = "file",required = false) MultipartFile file) throws Exception {
+        return innerApiService.uploadMatterproData(sceneName,userName,floor,sceneKind,file);
+    }
+
+    /**
+     * 查询上传matterpro数据状态
+     */
+    @CheckInnerApiPermit
+    @GetMapping("/getUploadMatterproDataStatus")
+    public ResultData getUploadMatterproDataStatus(@RequestParam(value = "num",required = true) String num) throws Exception {
+        return innerApiService.getUploadMatterproDataStatus(num);
+    }
+
+}

+ 60 - 0
src/main/java/com/fdkankan/scene/entity/Scene3dNumMatterPro.java

@@ -0,0 +1,60 @@
+package com.fdkankan.scene.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * matter_pro场景码
+ * </p>
+ *
+ * @author 
+ * @since 2022-11-24
+ */
+@Getter
+@Setter
+@TableName("t_scene_3d_num_matter_pro")
+public class Scene3dNumMatterPro implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @TableField("used")
+    private Integer used;
+
+    @TableField("folder_name")
+    private String folderName;
+
+    @TableField("code")
+    private String code;
+
+    /**
+     * 记录的状态,A: 生效,I: 禁用
+     */
+    @TableField("rec_status")
+    @TableLogic(value = "A", delval = "I")
+    private String recStatus;
+
+    /**
+     * 更新时间
+     */
+    @TableField("update_time")
+    private Date updateTime;
+
+    /**
+     * 创建时间
+     */
+    @TableField("create_time")
+    private Date createTime;
+
+
+}

+ 18 - 0
src/main/java/com/fdkankan/scene/mapper/IScene3dNumMatterProMapper.java

@@ -0,0 +1,18 @@
+package com.fdkankan.scene.mapper;
+
+import com.fdkankan.scene.entity.Scene3dNumMatterPro;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * matter_pro场景码 Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2022-11-24
+ */
+@Mapper
+public interface IScene3dNumMatterProMapper extends BaseMapper<Scene3dNumMatterPro> {
+
+}

+ 21 - 0
src/main/java/com/fdkankan/scene/service/IInnerApiService.java

@@ -0,0 +1,21 @@
+package com.fdkankan.scene.service;
+
+import com.fdkankan.web.response.ResultData;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * <p>
+ * TODO
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/11/24
+ **/
+public interface IInnerApiService {
+
+    ResultData uploadMatterproData(String sceneName,String userName,String floor,String sceneKind, MultipartFile file) throws Exception;
+
+    ResultData getUploadMatterproDataStatus(String num);
+
+}

+ 18 - 0
src/main/java/com/fdkankan/scene/service/IScene3dNumMatterProService.java

@@ -0,0 +1,18 @@
+package com.fdkankan.scene.service;
+
+import com.fdkankan.scene.entity.Scene3dNumMatterPro;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * matter_pro场景码 服务类
+ * </p>
+ *
+ * @author 
+ * @since 2022-11-24
+ */
+public interface IScene3dNumMatterProService extends IService<Scene3dNumMatterPro> {
+
+    Scene3dNumMatterPro findSceneNum();
+
+}

+ 258 - 0
src/main/java/com/fdkankan/scene/service/impl/InnerApiServiceImpl.java

@@ -0,0 +1,258 @@
+package com.fdkankan.scene.service.impl;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.RuntimeUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.common.constant.ErrorCode;
+import com.fdkankan.common.constant.SceneKind;
+import com.fdkankan.common.constant.SceneStatus;
+import com.fdkankan.common.exception.BusinessException;
+import com.fdkankan.common.util.FileUtils;
+import com.fdkankan.fyun.face.FYunFileServiceInterface;
+import com.fdkankan.model.constants.ConstantFilePath;
+import com.fdkankan.model.utils.CreateObjUtil;
+import com.fdkankan.redis.constant.RedisKey;
+import com.fdkankan.redis.constant.RedisLockKey;
+import com.fdkankan.redis.util.RedisLockUtil;
+import com.fdkankan.redis.util.RedisUtil;
+import com.fdkankan.scene.entity.Scene3dNumMatterPro;
+import com.fdkankan.scene.entity.ScenePro;
+import com.fdkankan.scene.entity.SceneProEdit;
+import com.fdkankan.scene.entity.User;
+import com.fdkankan.scene.service.IInnerApiService;
+import com.fdkankan.scene.service.IScene3dNumMatterProService;
+import com.fdkankan.scene.service.ISceneProEditService;
+import com.fdkankan.scene.service.ISceneProService;
+import com.fdkankan.scene.service.IUserService;
+import com.fdkankan.web.response.ResultData;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+import lombok.extern.slf4j.Slf4j;
+import org.joda.time.DateTime;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * <p>
+ * TODO
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/11/24
+ **/
+@Slf4j
+@Service
+public class InnerApiServiceImpl implements IInnerApiService {
+
+    @Value("${main.url}")
+    private String mainUrl;
+    @Value("${scene.pro.v3.url}")
+    private String sceneProV3Url;
+    @Autowired
+    private IScene3dNumMatterProService scene3dNumMatterProService;
+    @Autowired
+    private FYunFileServiceInterface fYunFileService;
+    @Autowired
+    private IUserService userService;
+    @Autowired
+    private ISceneProService sceneProService;
+    @Autowired
+    private ISceneProEditService sceneProEditService;
+    @Autowired
+    private RedisUtil redisUtil;
+    @Autowired
+    private RedisLockUtil redisLockUtil;
+
+    @Override
+    public ResultData uploadMatterproData(String sceneName, String userName, String floor, String sceneKind, MultipartFile file) throws Exception {
+        if(file == null || file.getSize() <=0){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_3001);
+        }
+
+        if(!file.getOriginalFilename().toLowerCase().endsWith(".zip") && !file.getOriginalFilename().toLowerCase().endsWith(".rar")){
+            throw new BusinessException(ErrorCode.FAILURE_CODE_5026);
+        }
+
+        boolean lock = redisLockUtil.lock(RedisLockKey.LOCK_GET_MATTERPRO_NUM, RedisKey.EXPIRE_TIME_1_MINUTE);
+        if(!lock){
+            throw new BusinessException(ErrorCode.SYSTEM_BUSY);
+        }
+        Scene3dNumMatterPro numEntity = scene3dNumMatterProService.findSceneNum();
+        String sceneNum = numEntity.getCode();
+        numEntity.setUsed(1);
+        scene3dNumMatterProService.updateById(numEntity);
+        redisLockUtil.unlockLua(RedisLockKey.LOCK_GET_MATTERPRO_NUM);
+
+        String dataSource = ConstantFilePath.BUILD_MODEL_PATH + UUID.randomUUID() + File.separator ;
+        JSONObject result = new JSONObject();
+        result.put("num", sceneNum);
+        result.put("dataSource", dataSource);
+        result.put("status", SceneStatus.wait.code());
+        String key = String.format(RedisKey.SCENE_UPLOAD_MATTERPRO_NUM, sceneNum);
+        redisUtil.set(key, result.toJSONString(), RedisKey.CAMERA_EXPIRE_7_TIME);
+
+        File data = new File(dataSource + file.getOriginalFilename());
+        if(!data.getParentFile().exists()){
+            data.getParentFile().mkdirs();
+        }
+        file.transferTo(data);
+
+        CompletableFuture.runAsync(() -> {
+            try {
+                if(file.getOriginalFilename().toLowerCase().endsWith(".zip")){
+                    CreateObjUtil.unZip(dataSource + file.getOriginalFilename(), dataSource);
+                }
+                if(file.getOriginalFilename().toLowerCase().endsWith(".rar")){
+                    CreateObjUtil.unRarWithPath(dataSource + file.getOriginalFilename(), dataSource);
+//            log.info("解压rar开始");
+//            String command = "unrar x " + dataSource + file.getOriginalFilename() + " " + dataSource;
+//            RuntimeUtil.exec(command);
+//            log.info("解压rar完毕:" + command);
+                }
+
+                Thread.sleep(2000L);
+
+                //删除压缩包
+                new File(dataSource + file.getOriginalFilename()).delete();
+
+                List<String> fileList = new ArrayList<>();
+                FileUtils.readfilePath(dataSource, fileList);
+                String ossPath = "";
+                Map<String, String> uploadMap = new HashMap<>();
+                for (String filePath : fileList) {
+                    ossPath = filePath.replace(dataSource, "images/images" + sceneNum + "/");
+                    if(ossPath.endsWith("/")){
+                        ossPath = ossPath.substring(0, ossPath.lastIndexOf("/"));
+                    }
+                    uploadMap.put(filePath, ossPath);
+                }
+                fYunFileService.uploadMulFiles(uploadMap);
+
+                ScenePro sceneProEntity = new ScenePro();
+                sceneProEntity.setDataSource(dataSource);
+                sceneProEntity.setNum(sceneNum);
+                sceneProEntity.setSceneDec("<p>四维看看 让空间讲故事</p>");
+                //默认场景名称,若有传场景名称,则以传的为准
+                sceneProEntity.setSceneName("手动上传场景");
+                if(StrUtil.isNotEmpty(sceneName)){
+                    sceneProEntity.setSceneName(sceneName);
+                }
+                sceneProEntity.setWebSite(mainUrl + "/" + sceneProV3Url + sceneNum);
+                sceneProEntity.setStatus(-2);
+                sceneProEntity.setPayStatus(1);
+                //默认用户id,若有传用户信息,则以传的为准
+                sceneProEntity.setUserId(2285L);
+                if(StrUtil.isNotEmpty(userName)){
+                    User userEntity = userService.findByUserName(userName);
+                    if(userEntity != null){
+                        sceneProEntity.setUserId(userEntity.getId());
+                    }
+                }
+                sceneProEntity.setSceneScheme(SceneKind.FACE.code().equals(sceneKind) ? 3 : 10);
+                sceneProEntity.setSceneSource(14);
+                sceneProEntity.setBuildType("V3");
+                sceneProEntity.setCreateTime(Calendar.getInstance().getTime());
+                sceneProService.save(sceneProEntity);
+
+                SceneProEdit sceneProEditEntity = new SceneProEdit();
+                sceneProEditEntity.setProId(sceneProEntity.getId());
+                sceneProEditEntity.setMapVisi(0);
+                sceneProEditEntity.setM2dVisi(1);
+                sceneProEditEntity.setM3dVisi(1);
+                sceneProEditEntity.setPanoVisi(1);
+                sceneProEditEntity.setCadImgVisi(0);
+                sceneProEditService.save(sceneProEditEntity);
+
+                JSONObject scenejson = JSONObject.parseObject(JSONObject.toJSONString(sceneProEntity));
+                scenejson.put("thumbImg", 0);
+                scenejson.put("version", 0);
+                scenejson.put("floorLogo", 0);
+                scenejson.put("sceneKey", "");
+                scenejson.put("public", 0);
+                scenejson.put("visions", 1);
+                scenejson.put("createTime", new DateTime(new Date()).toString("yyyy-MM-dd HH:mm"));
+
+                scenejson.put("floorPublishVer", sceneProEditEntity.getFloorPublishVer());
+                scenejson.put("floorEditVer", sceneProEditEntity.getFloorEditVer());
+                scenejson.put("entry", null);
+
+                scenejson.put("hots", 0);
+
+                FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data/data"+sceneNum+File.separator+"scene.json", scenejson.toString());
+
+                JSONObject floors = new JSONObject();
+                JSONArray floorArr = new JSONArray();
+                JSONObject floorObject = new JSONObject();
+                if(StrUtil.isEmpty(floor)){
+                    floorObject = new JSONObject();
+                    floorObject.put("id", 0);
+                    floorObject.put("subgroup", 0);
+                    floorObject.put("name", "1楼");
+                    floorObject.put("segment", new JSONArray());
+                    floorObject.put("vertex", new JSONArray());
+
+                    floorArr.add(floorObject);
+                }else {
+                    for(int i = 0; i < Integer.parseInt(floor); i ++){
+                        floorObject = new JSONObject();
+                        floorObject.put("id", i);
+                        floorObject.put("subgroup", i);
+                        floorObject.put("name", i+ 1 + "楼");
+                        floorObject.put("segment", new JSONArray());
+                        floorObject.put("vertex", new JSONArray());
+
+                        floorArr.add(floorObject);
+                    }
+                }
+                floors.put("floors", floorArr);
+                FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data/data"+sceneNum+File.separator+"floor.json",floors.toJSONString());
+                fYunFileService.uploadFile(ConstantFilePath.SCENE_PATH+"data/data"+sceneNum+File.separator+"floor.json", "data/data"+sceneNum+File.separator+"floor.json");
+                result.put("status", SceneStatus.NO_DISPLAY.code());
+                redisUtil.set(key, result.toJSONString(), RedisKey.CAMERA_EXPIRE_7_TIME);
+            }catch (Exception e){
+                result.put("status", SceneStatus.FAILD.code());
+                redisUtil.set(key, result.toJSONString(), RedisKey.CAMERA_EXPIRE_7_TIME);
+            }
+        });
+
+        return ResultData.ok(result);
+    }
+
+    @Override
+    public ResultData getUploadMatterproDataStatus(String num) {
+        String key = String.format(RedisKey.SCENE_UPLOAD_MATTERPRO_NUM, num);
+        String jsonStr = redisUtil.get(key);
+        if(StrUtil.isEmpty(jsonStr)){
+            throw new BusinessException(-1, "数据已过期,请前往个人中心查看");
+        }
+        JSONObject jsonObject = JSON.parseObject(jsonStr);
+        if(jsonObject.getInteger("status").equals(SceneStatus.NO_DISPLAY.code())){
+            ScenePro scenePro = sceneProService.findBySceneNum(num);
+            return ResultData.ok(scenePro);
+        }
+        return ResultData.ok(JSON.parseObject(jsonStr));
+    }
+
+    public static void main(String[] args) {
+//        List<String> fileList = new ArrayList<>();
+//        FileUtils.readfilePath("F:\\test\\wwwroot\\1115", fileList);
+////        List<String> strings = FileUtil.listFileNames("F:\\test\\wwwroot\\1115");
+//        fileList.stream().forEach(s-> System.out.println(s));
+//        System.out.println(FileUtil.getPrefix("1115.rar"));
+        FileUtil.move(new File("F:\\test\\wwwroot\\1115"), new File("F:\\test\\wwwroot"), true);
+
+
+    }
+}

+ 27 - 0
src/main/java/com/fdkankan/scene/service/impl/Scene3dNumMatterProServiceImpl.java

@@ -0,0 +1,27 @@
+package com.fdkankan.scene.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.fdkankan.common.constant.CommonStatus;
+import com.fdkankan.scene.entity.Scene3dNumMatterPro;
+import com.fdkankan.scene.mapper.IScene3dNumMatterProMapper;
+import com.fdkankan.scene.service.IScene3dNumMatterProService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * matter_pro场景码 服务实现类
+ * </p>
+ *
+ * @author 
+ * @since 2022-11-24
+ */
+@Service
+public class Scene3dNumMatterProServiceImpl extends ServiceImpl<IScene3dNumMatterProMapper, Scene3dNumMatterPro> implements IScene3dNumMatterProService {
+
+    @Override
+    public Scene3dNumMatterPro findSceneNum() {
+        return this.getOne(new LambdaQueryWrapper<Scene3dNumMatterPro>()
+            .eq(Scene3dNumMatterPro::getUsed, CommonStatus.NO.code()).last(" limit 1"));
+    }
+}

+ 238 - 0
src/main/resources/logback-nacos.xml

@@ -0,0 +1,238 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
+<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
+<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
+<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
+<configuration scan="true" scanPeriod="10 seconds">
+
+	<contextName>nacos</contextName>
+	<springProperty scope="context" name="LOG_PATH" source="logging.path"/>
+	<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
+	<property name="log.path" value="${LOG_PATH}/scenev3/logs" />
+
+	<!-- 彩色日志 -->
+	<!-- 彩色日志依赖的渲染类 -->
+	<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
+	<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
+	<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
+	<!-- 彩色日志格式 -->
+	<property name="CONSOLE_LOG_PATTERN"
+		value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
+
+	<!--输出到控制台 -->
+	<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+		<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息 -->
+		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+			<level>info</level>
+		</filter>
+		<encoder>
+			<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
+			<!-- 设置字符集 -->
+			<charset>UTF-8</charset>
+		</encoder>
+	</appender>
+	<!--输出到文件 -->
+
+	<!-- 时间滚动输出 level为 DEBUG 日志 -->
+	<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文件的路径及文件名 -->
+		<file>${log.path}/log_debug.log</file>
+		<!--日志文件输出格式 -->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}[%L] - %msg%n</pattern>
+			<charset>UTF-8</charset> <!-- 设置字符集 -->
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<!-- 日志归档 -->
+			<fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log
+			</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文件保留天数 -->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文件只记录debug级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>debug</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+
+	<appender name="ASYNC_DEBUG_FILE" class="com.yomahub.tlog.core.enhance.logback.async.AspectLogbackAsyncAppender">
+		<!--默认情况下,当BlockingQueue还有20%容量,他将丢弃TRACE、DEBUG和INFO级别的event,只保留WARN和ERROR级别的event。为了保持所有的events,设置该值为0。-->
+		<discardingThreshold>0</discardingThreshold>
+		<!--queue配置最大容量为256个events。如果队列被填满,应用程序线程被阻止记录新的events,直到工作线程有机会来转发一个或多个events。
+		因此队列深度需要根据业务场景进行相应的测试,做出相应的更改,以达到较好的性能。-->
+		<queueSize>2048</queueSize>
+		<includeCallerData>false</includeCallerData>
+		<appender-ref ref="DEBUG_FILE"/>
+	</appender>
+
+	<!-- 时间滚动输出 level为 INFO 日志 -->
+	<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文件的路径及文件名 -->
+		<file>${log.path}/log_info.log</file>
+		<!--日志文件输出格式 -->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}[%L] - %msg%n</pattern>
+			<charset>UTF-8</charset>
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<!-- 每天日志归档路径以及格式 -->
+			<fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log
+			</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文件保留天数 -->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文件只记录info级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>info</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+
+	<appender name="ASYNC_INFO_FILE" class="com.yomahub.tlog.core.enhance.logback.async.AspectLogbackAsyncAppender">
+		<!--默认情况下,当BlockingQueue还有20%容量,他将丢弃TRACE、DEBUG和INFO级别的event,只保留WARN和ERROR级别的event。为了保持所有的events,设置该值为0。-->
+		<discardingThreshold>0</discardingThreshold>
+		<!--queue配置最大容量为256个events。如果队列被填满,应用程序线程被阻止记录新的events,直到工作线程有机会来转发一个或多个events。
+		因此队列深度需要根据业务场景进行相应的测试,做出相应的更改,以达到较好的性能。-->
+		<queueSize>2048</queueSize>
+		<includeCallerData>false</includeCallerData>
+		<appender-ref ref="INFO_FILE"/>
+	</appender>
+
+	<!-- 时间滚动输出 level为 WARN 日志 -->
+	<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文件的路径及文件名 -->
+		<file>${log.path}/log_warn.log</file>
+		<!--日志文件输出格式 -->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}[%L] - %msg%n</pattern>
+			<charset>UTF-8</charset> <!-- 此处设置字符集 -->
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log
+			</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文件保留天数 -->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文件只记录warn级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>warn</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+
+	<appender name="ASYNC_WARN_FILE" class="com.yomahub.tlog.core.enhance.logback.async.AspectLogbackAsyncAppender">
+		<!--默认情况下,当BlockingQueue还有20%容量,他将丢弃TRACE、DEBUG和INFO级别的event,只保留WARN和ERROR级别的event。为了保持所有的events,设置该值为0。-->
+		<discardingThreshold>0</discardingThreshold>
+		<!--queue配置最大容量为256个events。如果队列被填满,应用程序线程被阻止记录新的events,直到工作线程有机会来转发一个或多个events。
+		因此队列深度需要根据业务场景进行相应的测试,做出相应的更改,以达到较好的性能。-->
+		<queueSize>2048</queueSize>
+		<includeCallerData>false</includeCallerData>
+		<appender-ref ref="WARN_FILE"/>
+	</appender>
+
+
+	<!-- 时间滚动输出 level为 ERROR 日志 -->
+	<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文件的路径及文件名 -->
+		<file>${log.path}/log_error.log</file>
+		<!--日志文件输出格式 -->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}[%L] - %msg%n</pattern>
+			<charset>UTF-8</charset> <!-- 此处设置字符集 -->
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log
+			</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文件保留天数 -->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文件只记录ERROR级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>ERROR</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+
+	<appender name="ASYNC_ERROR_FILE" class="com.yomahub.tlog.core.enhance.logback.async.AspectLogbackAsyncAppender">
+		<!--默认情况下,当BlockingQueue还有20%容量,他将丢弃TRACE、DEBUG和INFO级别的event,只保留WARN和ERROR级别的event。为了保持所有的events,设置该值为0。-->
+		<discardingThreshold>0</discardingThreshold>
+		<!--queue配置最大容量为256个events。如果队列被填满,应用程序线程被阻止记录新的events,直到工作线程有机会来转发一个或多个events。
+		因此队列深度需要根据业务场景进行相应的测试,做出相应的更改,以达到较好的性能。-->
+		<queueSize>2048</queueSize>
+		<includeCallerData>false</includeCallerData>
+		<appender-ref ref="ERROR_FILE"/>
+	</appender>
+
+
+	<springProperty scope="context" name="logstash_dest" source="logstash.ipAndPort"/>
+<!--	<springProperty scope="context" name="preIvkApp" source="logstash.preIvkApp"/>-->
+	<springProperty scope="context" name="application_name" source="spring.application.name"/>
+	<springProperty scope="context" name="profiles_active" source="spring.profiles.active"/>
+	<appender name="LOGSTASH_ERROR_FILE" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
+		<destination>${logstash_dest}</destination>
+		<keepAliveDuration>5 minutes</keepAliveDuration>
+		<!-- 日志输出编码 -->
+		<encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
+			<providers>
+				<provider class="com.yomahub.tlog.logstash.logback.TLogLogstashLogbackProvider"/>
+				<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
+				<pattern>
+					<pattern>
+						{
+						"level": "%level",
+						"thread": "%thread",
+						"class": "%logger{40}",
+						"message": "%message",
+						"stack_trace": "%exception{10}",
+						"client_time": "%d{yyyy-MM-dd HH:mm:ss.SSS}",
+						"preIvkApp":"${application_name}-${profiles_active}"
+						}
+					</pattern>
+				</pattern>
+			</providers>
+		</encoder>
+		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+			<level>ERROR</level>
+		</filter>
+	</appender>
+
+	<!-- <logger>用来设置某一个包或者具体的某一个类的日志打印级别、 以及指定<appender>。<logger>仅有一个name属性, 一个可选的level和一个可选的addtivity属性。 name:用来指定受此logger约束的某一个包或者具体的某一个类。 level:用来设置打印级别,大小写无关:TRACE,
+		DEBUG, INFO, WARN, ERROR, ALL 和 OFF, 还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。 如果未设置此属性,那么当前logger将会继承上级的级别。 addtivity:是否向上级logger传递打印信息。默认是true。 -->
+	<!--<logger name="org.springframework.web" level="info"/> -->
+	<!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/> -->
+	<!-- 使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作: 第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息 第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别: -->
+	<!-- root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性 level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF, 不能设置为INHERITED或者同义词NULL。默认是DEBUG 可以包含零个或多个元素,标识这个appender将会添加到这个logger。 -->
+
+	<root level="info">
+		<appender-ref ref="CONSOLE" />
+		<appender-ref ref="ASYNC_DEBUG_FILE" />
+		<appender-ref ref="ASYNC_INFO_FILE" />
+		<appender-ref ref="ASYNC_WARN_FILE" />
+		<appender-ref ref="ASYNC_ERROR_FILE" />
+		<appender-ref ref="LOGSTASH_ERROR_FILE"/>
+	</root>
+
+</configuration>
+
+

+ 5 - 0
src/main/resources/mapper/scene/Scene3dNumMatterProMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fdkankan.scene.mapper.IScene3dNumMatterProMapper">
+
+</mapper>