From a394004c66ce2dc9ddce459bc5af2ac6d4a76c15 Mon Sep 17 00:00:00 2001 From: qiushui Date: Mon, 13 Dec 2021 15:11:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9F=BA=E7=A1=80=E7=89=88=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 5 -- web/pom.xml | 10 +-- .../web/config/ConfigProperties.java | 8 ++ .../web/controller/StockController.java | 6 -- .../com/zhehekeji/web/entity/Category.java | 2 + .../zhehekeji/web/entity/KsecUpPcInfo.java | 24 ----- .../java/com/zhehekeji/web/entity/Stock.java | 3 + .../zhehekeji/web/mapper/CategoryMapper.java | 4 +- .../zhehekeji/web/mapper/KsecUpPcMapper.java | 7 -- .../zhehekeji/web/pojo/stock/StockExcel.java | 4 +- .../web/service/CategoryImportListener.java | 48 ++++++++++ .../web/service/CategoryService.java | 49 +++++------ .../zhehekeji/web/service/InitService.java | 8 +- .../com/zhehekeji/web/service/PlcService.java | 2 +- .../web/service/ksec/KsecDecoder.java | 5 ++ .../web/service/ksec/KsecNettyClient.java | 11 ++- .../web/service/robotic/ProtocolDecoder.java | 7 +- web/src/main/resources/application-dev.yml | 17 +--- web/src/main/resources/application-prod.yml | 43 +++++---- web/src/main/resources/application-test.yml | 43 +++++---- web/src/main/resources/application.yml | 11 ++- web/src/main/resources/logback-spring.xml | 82 +++++++++++------- web/src/main/resources/品规模板.xlsx | Bin 10151 -> 11571 bytes web/src/main/resources/库存模板.xlsx | Bin 10748 -> 12292 bytes 24 files changed, 216 insertions(+), 183 deletions(-) delete mode 100644 web/src/main/java/com/zhehekeji/web/entity/KsecUpPcInfo.java delete mode 100644 web/src/main/java/com/zhehekeji/web/mapper/KsecUpPcMapper.java create mode 100644 web/src/main/java/com/zhehekeji/web/service/CategoryImportListener.java diff --git a/pom.xml b/pom.xml index dcb87b9..81b11fc 100644 --- a/pom.xml +++ b/pom.xml @@ -55,11 +55,6 @@ org.apache.commons commons-lang3 - - com.google.guava - guava - 18.0 - diff --git a/web/pom.xml b/web/pom.xml index ca8a470..f264636 100644 --- a/web/pom.xml +++ b/web/pom.xml @@ -28,11 +28,11 @@ org.springframework.boot spring-boot-starter-cache - - com.google.guava - guava - 18.0 - + + + + + org.springframework.boot spring-boot-starter-web diff --git a/web/src/main/java/com/zhehekeji/web/config/ConfigProperties.java b/web/src/main/java/com/zhehekeji/web/config/ConfigProperties.java index 7704f0a..7d2fc40 100644 --- a/web/src/main/java/com/zhehekeji/web/config/ConfigProperties.java +++ b/web/src/main/java/com/zhehekeji/web/config/ConfigProperties.java @@ -29,6 +29,8 @@ public class ConfigProperties { private String userUrl; + private KSEC ksec; + @Data public static class CameraConfig{ @@ -52,4 +54,10 @@ public class ConfigProperties { private String mediaPath; private String mp4Path; } + + @Data + public static class KSEC{ + private String ip; + private Integer port; + } } diff --git a/web/src/main/java/com/zhehekeji/web/controller/StockController.java b/web/src/main/java/com/zhehekeji/web/controller/StockController.java index acaed88..0648b34 100644 --- a/web/src/main/java/com/zhehekeji/web/controller/StockController.java +++ b/web/src/main/java/com/zhehekeji/web/controller/StockController.java @@ -119,10 +119,4 @@ public class StockController { } - @ApiOperation(value = "currentPosition") - @RequestMapping(value = "/currentPosition", method = RequestMethod.GET) - public Result currentPosition(Integer cameraId,Integer ptzId) { - JoywarePtzControlModule.turn360C8(cameraId,ptzId); - return Result.success(); - } } diff --git a/web/src/main/java/com/zhehekeji/web/entity/Category.java b/web/src/main/java/com/zhehekeji/web/entity/Category.java index 9baca87..bafbc90 100644 --- a/web/src/main/java/com/zhehekeji/web/entity/Category.java +++ b/web/src/main/java/com/zhehekeji/web/entity/Category.java @@ -20,6 +20,8 @@ public class Category { @TableId(type = IdType.AUTO) private Integer id; + private String code; + private String name; @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") diff --git a/web/src/main/java/com/zhehekeji/web/entity/KsecUpPcInfo.java b/web/src/main/java/com/zhehekeji/web/entity/KsecUpPcInfo.java deleted file mode 100644 index 7f7ae46..0000000 --- a/web/src/main/java/com/zhehekeji/web/entity/KsecUpPcInfo.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.zhehekeji.web.entity; - -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 昆船上位机信息 - */ -@Data -@TableName("ksec_up_pc_info") -public class KsecUpPcInfo { - - private Integer id; - - private String ip; - - private Integer port; - - private String name; - - private LocalDateTime createTime; -} diff --git a/web/src/main/java/com/zhehekeji/web/entity/Stock.java b/web/src/main/java/com/zhehekeji/web/entity/Stock.java index 5df24a1..a95f08c 100644 --- a/web/src/main/java/com/zhehekeji/web/entity/Stock.java +++ b/web/src/main/java/com/zhehekeji/web/entity/Stock.java @@ -19,6 +19,9 @@ public class Stock { private String orderNum; + @ApiModelProperty("条码") + private String code; + @ApiModelProperty("品规名称") private String category; diff --git a/web/src/main/java/com/zhehekeji/web/mapper/CategoryMapper.java b/web/src/main/java/com/zhehekeji/web/mapper/CategoryMapper.java index be7cd24..e8be1a9 100644 --- a/web/src/main/java/com/zhehekeji/web/mapper/CategoryMapper.java +++ b/web/src/main/java/com/zhehekeji/web/mapper/CategoryMapper.java @@ -6,6 +6,6 @@ import org.apache.ibatis.annotations.Select; public interface CategoryMapper extends BaseMapper { - @Select(" select * from category where name = #{name} limit 1") - Category getByName(String name); + @Select(" select * from category where code = #{code} limit 1") + Category getByCode(String code); } diff --git a/web/src/main/java/com/zhehekeji/web/mapper/KsecUpPcMapper.java b/web/src/main/java/com/zhehekeji/web/mapper/KsecUpPcMapper.java deleted file mode 100644 index 945d87a..0000000 --- a/web/src/main/java/com/zhehekeji/web/mapper/KsecUpPcMapper.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.zhehekeji.web.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.zhehekeji.web.entity.KsecUpPcInfo; - -public interface KsecUpPcMapper extends BaseMapper { -} diff --git a/web/src/main/java/com/zhehekeji/web/pojo/stock/StockExcel.java b/web/src/main/java/com/zhehekeji/web/pojo/stock/StockExcel.java index c9d2bf3..267ca59 100644 --- a/web/src/main/java/com/zhehekeji/web/pojo/stock/StockExcel.java +++ b/web/src/main/java/com/zhehekeji/web/pojo/stock/StockExcel.java @@ -6,8 +6,8 @@ import lombok.Data; @Data public class StockExcel { - @ExcelProperty(index = 0, value = "品规") - private String category; + @ExcelProperty(index = 0, value = "条码") + private String code; @ExcelProperty(index = 1, value = "数量") private Integer count; diff --git a/web/src/main/java/com/zhehekeji/web/service/CategoryImportListener.java b/web/src/main/java/com/zhehekeji/web/service/CategoryImportListener.java new file mode 100644 index 0000000..56c3b2b --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/service/CategoryImportListener.java @@ -0,0 +1,48 @@ +package com.zhehekeji.web.service; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.zhehekeji.web.entity.CameraIOConfig; +import com.zhehekeji.web.entity.Category; +import com.zhehekeji.web.mapper.CameraIOConfigMapper; +import com.zhehekeji.web.mapper.CategoryMapper; +import com.zhehekeji.web.pojo.camera.IOImport; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.stream.Collectors; + +/** + * IO表导入 + */ +@Slf4j +public class CategoryImportListener extends AnalysisEventListener { + + private CategoryMapper categoryMapper; + + public CategoryImportListener(CategoryMapper categoryMapper){ + this.categoryMapper = categoryMapper; + } + + @Override + public void invoke(Category category, AnalysisContext analysisContext) { + Category old = categoryMapper.getByCode(category.getCode()); + if(old == null){ + category.setUpdateTime(LocalDateTime.now()); + categoryMapper.insert(category); + }else { + //更改名字 + old.setName(category.getName()); + old.setUpdateTime(LocalDateTime.now()); + } + + } + + @Override + public void doAfterAllAnalysed(AnalysisContext analysisContext) { + + } +} diff --git a/web/src/main/java/com/zhehekeji/web/service/CategoryService.java b/web/src/main/java/com/zhehekeji/web/service/CategoryService.java index cb6f347..6c13cd4 100644 --- a/web/src/main/java/com/zhehekeji/web/service/CategoryService.java +++ b/web/src/main/java/com/zhehekeji/web/service/CategoryService.java @@ -1,6 +1,7 @@ package com.zhehekeji.web.service; import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.read.builder.ExcelReaderBuilder; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.github.pagehelper.PageHelper; @@ -8,6 +9,7 @@ import com.github.pagehelper.PageInfo; import com.zhehekeji.core.util.Assert; import com.zhehekeji.web.entity.Category; import com.zhehekeji.web.mapper.CategoryMapper; +import com.zhehekeji.web.pojo.camera.IOImport; import com.zhehekeji.web.pojo.category.CategoryExcel; import com.zhehekeji.web.pojo.category.CategoryModel; import com.zhehekeji.web.pojo.category.PageSearch; @@ -76,6 +78,11 @@ public class CategoryService { return category.getId(); } +// public void importExcel(MultipartFile file) throws IOException { +// EasyExcel.read(file.getInputStream(), Category.class, new CategoryImportListener(categoryMapper)).sheet().doRead(); +// return; +// } + public Integer importExcel(MultipartFile file) throws IOException { XSSFWorkbook wb = new XSSFWorkbook(file.getInputStream()); XSSFSheet sheet = wb.getSheetAt(0); @@ -97,36 +104,28 @@ public class CategoryService { int columns = firstRow.getLastCellNum(); for (int i = 1; i < rows; i++) { XSSFRow row = sheet.getRow(i); - StringBuffer category = new StringBuffer(); - for(int j = 0;j 0){ - category.deleteCharAt(category.length()-1); + XSSFCell cell1 = row.getCell(1); + if(cell1 != null){ + String name = cell.getStringCellValue(); + category.setName(name); } - insert(category.toString()); - } - } - - public Integer insert(String name){ - Category category = categoryMapper.getByName(name); - if(category == null){ - category = new Category(); - category.setName(name); - category.setUpdateTime(LocalDateTime.now()); - try { + Category old = categoryMapper.getByCode(category.getCode()); + if(old == null){ + category.setUpdateTime(LocalDateTime.now()); categoryMapper.insert(category); - }catch (DuplicateKeyException e){ - log.warn("品规已存在:{}",name); + }else { + //更改名字 + old.setName(category.getName()); + old.setUpdateTime(LocalDateTime.now()); + categoryMapper.updateById(old); } } - return category.getId(); } } diff --git a/web/src/main/java/com/zhehekeji/web/service/InitService.java b/web/src/main/java/com/zhehekeji/web/service/InitService.java index fa74c4a..3e8eee2 100644 --- a/web/src/main/java/com/zhehekeji/web/service/InitService.java +++ b/web/src/main/java/com/zhehekeji/web/service/InitService.java @@ -2,17 +2,14 @@ package com.zhehekeji.web.service; import com.zhehekeji.web.config.ConfigProperties; import com.zhehekeji.web.entity.Camera; -import com.zhehekeji.web.entity.KsecUpPcInfo; import com.zhehekeji.web.entity.Street; import com.zhehekeji.web.lib.*; import com.zhehekeji.web.lib.joyware.NetSDKLib; import com.zhehekeji.web.mapper.CameraMapper; -import com.zhehekeji.web.mapper.KsecUpPcMapper; import com.zhehekeji.web.mapper.StreetMapper; import com.zhehekeji.web.service.ksec.KsecNettyClient; import com.zhehekeji.web.service.robotic.NettyClient; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; @@ -44,9 +41,6 @@ public class InitService implements ApplicationRunner { @Resource private ConfigProperties configProperties; - @Resource - private KsecUpPcMapper upPcMapper; - @Override public void run(ApplicationArguments args) throws Exception { //球机登录 @@ -74,7 +68,7 @@ public class InitService implements ApplicationRunner { }else if(configProperties.getServerMode() == 1){ log.info("KESC JSON MODE"); // 昆船协议 - KsecUpPcInfo ksec = upPcMapper.selectById(1); + ConfigProperties.KSEC ksec = configProperties.getKsec(); if(ksec != null){ StreetConn.init(1,"ksec"); try { diff --git a/web/src/main/java/com/zhehekeji/web/service/PlcService.java b/web/src/main/java/com/zhehekeji/web/service/PlcService.java index 75621b9..4b63819 100644 --- a/web/src/main/java/com/zhehekeji/web/service/PlcService.java +++ b/web/src/main/java/com/zhehekeji/web/service/PlcService.java @@ -63,7 +63,7 @@ public class PlcService { } /** - * 开始工单 + * 开始工单 robotic plcId是plcId,昆船的plcId是来自包体,即srmNumber * @param plcOrderInfo * @param plcId */ diff --git a/web/src/main/java/com/zhehekeji/web/service/ksec/KsecDecoder.java b/web/src/main/java/com/zhehekeji/web/service/ksec/KsecDecoder.java index e7f25c9..5f1e9b1 100644 --- a/web/src/main/java/com/zhehekeji/web/service/ksec/KsecDecoder.java +++ b/web/src/main/java/com/zhehekeji/web/service/ksec/KsecDecoder.java @@ -8,6 +8,8 @@ import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.DelimiterBasedFrameDecoder; import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.nio.charset.Charset; @@ -17,6 +19,8 @@ import java.nio.charset.Charset; @Slf4j public class KsecDecoder extends DelimiterBasedFrameDecoder { + private static final Logger tcpLogger = LoggerFactory.getLogger("tcp"); + private PlcService plcService; public KsecDecoder(int maxFrameLength, ByteBuf delimiter, PlcService plcService) { @@ -32,6 +36,7 @@ public class KsecDecoder extends DelimiterBasedFrameDecoder { // 去掉首尾标识符 body = body.substring(1, body.length()); KsecInfo ksecInfo = JSONObject.parseObject(body, KsecInfo.class); + tcpLogger.info("info:{}",body); log.info("receieve info:{}", ksecInfo); KsecDataInfo dataInfo = ksecInfo.getData(); PlcOrderInfo plcOrderInfo = null; diff --git a/web/src/main/java/com/zhehekeji/web/service/ksec/KsecNettyClient.java b/web/src/main/java/com/zhehekeji/web/service/ksec/KsecNettyClient.java index 4bd4755..715a90a 100644 --- a/web/src/main/java/com/zhehekeji/web/service/ksec/KsecNettyClient.java +++ b/web/src/main/java/com/zhehekeji/web/service/ksec/KsecNettyClient.java @@ -1,8 +1,7 @@ package com.zhehekeji.web.service.ksec; -import com.zhehekeji.web.entity.KsecUpPcInfo; -import com.zhehekeji.web.mapper.KsecUpPcMapper; +import com.zhehekeji.web.config.ConfigProperties; import com.zhehekeji.web.service.PlcService; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; @@ -23,7 +22,7 @@ public class KsecNettyClient { @Resource private PlcService plcService; @Resource - private KsecUpPcMapper ksecUpPcMapper; + private ConfigProperties configProperties; /** * 重连最大次数 @@ -32,7 +31,7 @@ public class KsecNettyClient { private static Channel channel; - public void createClient(KsecUpPcInfo ksec){ + public void createClient(ConfigProperties.KSEC ksec){ if (StringUtils.isEmpty(ksec.getIp()) || ksec.getPort() == null) { return; } @@ -59,7 +58,7 @@ public class KsecNettyClient { public void reconnect(Integer upId) { Boolean isConnected = false; int num = 0; - KsecUpPcInfo ksec = ksecUpPcMapper.selectById(upId); + ConfigProperties.KSEC ksec = configProperties.getKsec(); if (ksec == null) { log.error("reconnect ,upPc is null ,id:{}", upId); return; @@ -78,7 +77,7 @@ public class KsecNettyClient { if (isConnected) { log.info("plc reconnect success"); } else { - log.error("plc reconnect error .upPcId:{},reconnect num:{},name:{},ip:{},port:{}", upId, num, ksec.getName(), ksec.getIp(), ksec.getPort()); + log.error("plc reconnect error .upPcId:{},reconnect num:{},ip:{},port:{}", upId, num, ksec.getIp(), ksec.getPort()); } } diff --git a/web/src/main/java/com/zhehekeji/web/service/robotic/ProtocolDecoder.java b/web/src/main/java/com/zhehekeji/web/service/robotic/ProtocolDecoder.java index c7c08bd..dbff7c4 100644 --- a/web/src/main/java/com/zhehekeji/web/service/robotic/ProtocolDecoder.java +++ b/web/src/main/java/com/zhehekeji/web/service/robotic/ProtocolDecoder.java @@ -7,6 +7,8 @@ import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.FixedLengthFrameDecoder; import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.nio.charset.Charset; @@ -14,6 +16,8 @@ import java.nio.charset.Charset; @Slf4j public class ProtocolDecoder extends FixedLengthFrameDecoder { + private static final Logger tcpLogger = LoggerFactory.getLogger("tcp"); + private PlcService plcService; public ProtocolDecoder(PlcService plcService) { @@ -85,7 +89,8 @@ public class ProtocolDecoder extends FixedLengthFrameDecoder { //String barCodeSys = String.valueOf(b5)+b6+b7+b8; String barCodeSys = new String(bytesBarNumSys, "UTF-8"); if(!type.equals(HEART)){ - log.info("plcId:{},原始信号:{}", plcId, signal); + //log.info("plcId:{},原始信号:{}", plcId, signal); + tcpLogger.info("plcId:{},原始信号:{}", plcId, signal); } if (type.equals(HEART)) { //心跳 diff --git a/web/src/main/resources/application-dev.yml b/web/src/main/resources/application-dev.yml index 8cd6e64..4039734 100644 --- a/web/src/main/resources/application-dev.yml +++ b/web/src/main/resources/application-dev.yml @@ -1,8 +1,3 @@ -logging: - level: - com.zhehekeji: debug - org.springframework.web: info - root: info spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver @@ -22,13 +17,6 @@ spring: url: jdbc:mysql://115.236.65.98:12004/lia_duoji?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8 username: root validationQuery: SELECT 1 FROM DUAL -zhehe: - common: - redis: - prefix: spring - filter: - enable: true - postToken: w89euijon2&UHBTY$%huni34ri # --------本服务端口号 server: port: 8099 @@ -48,8 +36,11 @@ cameraConfig: savePath: mediaPath: d:\\data\media\ mp4Path: d:\\data\mp4\ -# ------------服务端类型 0:TCP(罗伯泰克) 1:JSON(昆船) +# ------------服务端类型 0:TCP(罗伯泰克) 1:KSEC(JSON)(昆船) serverMode: 1 +ksec: + ip: 127.0.0.1 + port: 3000 # ------------ 实时视频流 全部页面的格式 行列数量 videoStyleConfig: videoStyleRow: 2 diff --git a/web/src/main/resources/application-prod.yml b/web/src/main/resources/application-prod.yml index 604f94b..a6f7824 100644 --- a/web/src/main/resources/application-prod.yml +++ b/web/src/main/resources/application-prod.yml @@ -1,8 +1,3 @@ -logging: - level: - com.zhehekeji: debug - org.springframework.web: info - root: info spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver @@ -22,13 +17,6 @@ spring: url: jdbc:mysql://115.236.65.98:12004/lia_duoji?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8 username: root validationQuery: SELECT 1 FROM DUAL -zhehe: - common: - redis: - prefix: spring - filter: - enable: true - postToken: w89euijon2&UHBTY$%huni34ri # --------本服务端口号 server: port: 8099 @@ -37,19 +25,28 @@ server: userUrl: http://115.236.65.98:11001 # ----------- # ----默认摄像头的连接信息 -cameraPassword: admin123 -cameraUser: admin -cameraPort: 37777 +cameraConfig: + # ------------球機選擇--- 0:中威 1:海康 + cameraType: 0 + cameraPassword: admin123 + cameraUser: admin + cameraPort: 37777 # ------------ # -----图片 mp4下载地址 -mediaPath: d:\\data\media\ -mp4Path: d:\\data\mp4\ -# ------------球機選擇--- 0:中威 1:海康 -cameraType: 1 -# ------------服务端类型 0:TCP 1:JSON +savePath: + mediaPath: d:\\data\media\ + mp4Path: d:\\data\mp4\ +# ------------服务端类型 0:TCP(罗伯泰克) 1:KSEC(JSON)(昆船) serverMode: 1 +ksec: + ip: 127.0.0.1 + port: 3000 # ------------ 实时视频流 全部页面的格式 行列数量 -videoStyleRow: 2 -videoStyleColumn: 2 +videoStyleConfig: + videoStyleRow: 2 + videoStyleColumn: 2 # ------------球机m3u8默认地址 %d是球机数据库id,如果数据库没有,就使用此默认值 -mediaServer: http://127.0.0.1:9080/hls/camera%d.m3u8 \ No newline at end of file +mediaServer: http://127.0.0.1:9080/hls/camera%d.m3u8 +rtcServer: + rtcServerIp: 127.0.0.1 + rtcServerPort: 8083 \ No newline at end of file diff --git a/web/src/main/resources/application-test.yml b/web/src/main/resources/application-test.yml index 604f94b..a6f7824 100644 --- a/web/src/main/resources/application-test.yml +++ b/web/src/main/resources/application-test.yml @@ -1,8 +1,3 @@ -logging: - level: - com.zhehekeji: debug - org.springframework.web: info - root: info spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver @@ -22,13 +17,6 @@ spring: url: jdbc:mysql://115.236.65.98:12004/lia_duoji?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8 username: root validationQuery: SELECT 1 FROM DUAL -zhehe: - common: - redis: - prefix: spring - filter: - enable: true - postToken: w89euijon2&UHBTY$%huni34ri # --------本服务端口号 server: port: 8099 @@ -37,19 +25,28 @@ server: userUrl: http://115.236.65.98:11001 # ----------- # ----默认摄像头的连接信息 -cameraPassword: admin123 -cameraUser: admin -cameraPort: 37777 +cameraConfig: + # ------------球機選擇--- 0:中威 1:海康 + cameraType: 0 + cameraPassword: admin123 + cameraUser: admin + cameraPort: 37777 # ------------ # -----图片 mp4下载地址 -mediaPath: d:\\data\media\ -mp4Path: d:\\data\mp4\ -# ------------球機選擇--- 0:中威 1:海康 -cameraType: 1 -# ------------服务端类型 0:TCP 1:JSON +savePath: + mediaPath: d:\\data\media\ + mp4Path: d:\\data\mp4\ +# ------------服务端类型 0:TCP(罗伯泰克) 1:KSEC(JSON)(昆船) serverMode: 1 +ksec: + ip: 127.0.0.1 + port: 3000 # ------------ 实时视频流 全部页面的格式 行列数量 -videoStyleRow: 2 -videoStyleColumn: 2 +videoStyleConfig: + videoStyleRow: 2 + videoStyleColumn: 2 # ------------球机m3u8默认地址 %d是球机数据库id,如果数据库没有,就使用此默认值 -mediaServer: http://127.0.0.1:9080/hls/camera%d.m3u8 \ No newline at end of file +mediaServer: http://127.0.0.1:9080/hls/camera%d.m3u8 +rtcServer: + rtcServerIp: 127.0.0.1 + rtcServerPort: 8083 \ No newline at end of file diff --git a/web/src/main/resources/application.yml b/web/src/main/resources/application.yml index d0f5ce9..e889152 100644 --- a/web/src/main/resources/application.yml +++ b/web/src/main/resources/application.yml @@ -2,7 +2,7 @@ spring: profiles: active: @profileActive@ application: - name: springbootstart-web + name: duoji-web mvc: #视图路径配置 view: @@ -21,3 +21,12 @@ mapper: identity: MYSQL not-empty: true style: normal +zhehe: + common: + redis: + prefix: spring + filter: + enable: true + postToken: w89euijon2&UHBTY$%huni34ri +logging: + config: classpath:logback-spring.xml \ No newline at end of file diff --git a/web/src/main/resources/logback-spring.xml b/web/src/main/resources/logback-spring.xml index f4d84cf..ffc8110 100644 --- a/web/src/main/resources/logback-spring.xml +++ b/web/src/main/resources/logback-spring.xml @@ -2,13 +2,16 @@ - - - %d %p (%file:%line\)- %m%n + + + + [%d{yyyy-MM-dd HH:mm:ss.SSS}] %level [%thread] %file:%line - %msg%n UTF-8 - + + + ${LOG_HOME}/${logName}-info.log ${LOG_HOME}/${logName}-info-%d{yyyy-MM-dd}.%i.log @@ -29,7 +32,8 @@ DENY - + + ${LOG_HOME}/${logName}-warn.log ${LOG_HOME}/${logName}-warn-%d{yyyy-MM-dd}.%i.log @@ -45,12 +49,14 @@ UTF-8 - warn + WARN ACCEPT DENY - + + + ${LOG_HOME}/${logName}-error.log ${LOG_HOME}/${logName}-error-%d{yyyy-MM-dd}.%i.log @@ -72,29 +78,41 @@ - - - - - - - - - - - - - - - - + + + + + ${LOG_HOME}/${logName}-tcp.log + + ${LOG_HOME}/${logName}-tcp-%d{yyyy-MM-dd}.%i.log + 30 + + 10MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + info + ACCEPT + DENY + + + + + + + + + + + + + + - - - - - - - - - + \ No newline at end of file diff --git a/web/src/main/resources/品规模板.xlsx b/web/src/main/resources/品规模板.xlsx index c379a2461506ac3601c83119e9f03fa65765d16e..d26f873360eaffa33883609c056ebc64bb719f18 100644 GIT binary patch literal 11571 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 DA3Sko diff --git a/web/src/main/resources/库存模板.xlsx b/web/src/main/resources/库存模板.xlsx index 7bb54145ba5ed7cdcd38d808063f6d5f161c5d98..65fc5d9031f66a317970a5b6a4df055c970d3adf 100644 GIT binary patch literal 12292 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