Commit ff6c5ef57dbca0b883905c9a1aff3d6a488e1965
1 parent
5077713e
fix():添加FTP配置,添加历史视频回放在多人情况下的友好提示
Showing
52 changed files
with
2446 additions
and
712 deletions
pom.xml
| @@ -95,6 +95,19 @@ | @@ -95,6 +95,19 @@ | ||
| 95 | </profiles> | 95 | </profiles> |
| 96 | 96 | ||
| 97 | <dependencies> | 97 | <dependencies> |
| 98 | + <!-- https://mvnrepository.com/artifact/commons-net/commons-net --> | ||
| 99 | + <dependency> | ||
| 100 | + <groupId>commons-net</groupId> | ||
| 101 | + <artifactId>commons-net</artifactId> | ||
| 102 | + <version>3.9.0</version> | ||
| 103 | + </dependency> | ||
| 104 | + | ||
| 105 | + <!-- hutool --> | ||
| 106 | + <dependency> | ||
| 107 | + <groupId>cn.hutool</groupId> | ||
| 108 | + <artifactId>hutool-all</artifactId> | ||
| 109 | + <version>5.7.22</version> | ||
| 110 | + </dependency> | ||
| 98 | <dependency> | 111 | <dependency> |
| 99 | <groupId>org.springframework.boot</groupId> | 112 | <groupId>org.springframework.boot</groupId> |
| 100 | <artifactId>spring-boot-starter-data-redis</artifactId> | 113 | <artifactId>spring-boot-starter-data-redis</artifactId> |
| @@ -176,13 +189,6 @@ | @@ -176,13 +189,6 @@ | ||
| 176 | <scope>system</scope> | 189 | <scope>system</scope> |
| 177 | <systemPath>${basedir}/libs/jdbc-aarch/kingbase8-8.6.0.jar</systemPath> | 190 | <systemPath>${basedir}/libs/jdbc-aarch/kingbase8-8.6.0.jar</systemPath> |
| 178 | </dependency> | 191 | </dependency> |
| 179 | - <dependency> | ||
| 180 | - <groupId>com.kingbase</groupId> | ||
| 181 | - <artifactId>kingbase8</artifactId> | ||
| 182 | - <version>8.6.0</version> | ||
| 183 | - <scope>system</scope> | ||
| 184 | - <systemPath>${basedir}/libs/jdbc-x86/kingbase8-8.6.0.jar</systemPath> | ||
| 185 | - </dependency> | ||
| 186 | 192 | ||
| 187 | <!--Mybatis分页插件 --> | 193 | <!--Mybatis分页插件 --> |
| 188 | <dependency> | 194 | <dependency> |
| @@ -210,14 +216,6 @@ | @@ -210,14 +216,6 @@ | ||
| 210 | <version>3.6.1</version> | 216 | <version>3.6.1</version> |
| 211 | </dependency> | 217 | </dependency> |
| 212 | 218 | ||
| 213 | - | ||
| 214 | - <!--在线文档 --> | ||
| 215 | - <dependency> | ||
| 216 | - <groupId>org.springdoc</groupId> | ||
| 217 | - <artifactId>springdoc-openapi-ui</artifactId> | ||
| 218 | - <version>1.6.10</version> | ||
| 219 | - </dependency> | ||
| 220 | - | ||
| 221 | <dependency> | 219 | <dependency> |
| 222 | <groupId>com.github.xiaoymin</groupId> | 220 | <groupId>com.github.xiaoymin</groupId> |
| 223 | <artifactId>knife4j-springdoc-ui</artifactId> | 221 | <artifactId>knife4j-springdoc-ui</artifactId> |
| @@ -290,12 +288,6 @@ | @@ -290,12 +288,6 @@ | ||
| 290 | <version>2.7</version> | 288 | <version>2.7</version> |
| 291 | </dependency> | 289 | </dependency> |
| 292 | 290 | ||
| 293 | - <dependency> | ||
| 294 | - <groupId>com.xiaoleilu</groupId> | ||
| 295 | - <artifactId>hutool-all</artifactId> | ||
| 296 | - <version>3.1.0</version> | ||
| 297 | - </dependency> | ||
| 298 | - | ||
| 299 | <!-- https://mvnrepository.com/artifact/net.sf.kxml/kxml2 --> | 291 | <!-- https://mvnrepository.com/artifact/net.sf.kxml/kxml2 --> |
| 300 | <!-- <dependency>--> | 292 | <!-- <dependency>--> |
| 301 | <!-- <groupId>net.sf.kxml</groupId>--> | 293 | <!-- <groupId>net.sf.kxml</groupId>--> |
| @@ -361,12 +353,6 @@ | @@ -361,12 +353,6 @@ | ||
| 361 | <artifactId>guava</artifactId> | 353 | <artifactId>guava</artifactId> |
| 362 | <version>32.1.3-jre</version> | 354 | <version>32.1.3-jre</version> |
| 363 | </dependency> | 355 | </dependency> |
| 364 | - | ||
| 365 | - <dependency> | ||
| 366 | - <groupId>org.springframework.boot</groupId> | ||
| 367 | - <artifactId>spring-boot-starter-test</artifactId> | ||
| 368 | - <scope>test</scope> | ||
| 369 | - </dependency> | ||
| 370 | </dependencies> | 356 | </dependencies> |
| 371 | 357 | ||
| 372 | <build> | 358 | <build> |
src/main/java/com/genersoft/iot/vmp/TCPClient.java
| @@ -7,7 +7,7 @@ import java.net.Socket; | @@ -7,7 +7,7 @@ import java.net.Socket; | ||
| 7 | public class TCPClient { | 7 | public class TCPClient { |
| 8 | public static void main(String[] args) throws Exception{ | 8 | public static void main(String[] args) throws Exception{ |
| 9 | //创建socket,并指定连接的是本机的端口号为65000的服务器socket | 9 | //创建socket,并指定连接的是本机的端口号为65000的服务器socket |
| 10 | - Socket socket = new Socket("118.113.164.50",3333); | 10 | + Socket socket = new Socket("61.169.120.202",40000); |
| 11 | //获取输出流 | 11 | //获取输出流 |
| 12 | OutputStream os = socket.getOutputStream(); | 12 | OutputStream os = socket.getOutputStream(); |
| 13 | //获取输入流 | 13 | //获取输入流 |
src/main/java/com/genersoft/iot/vmp/TCPServer.java
| @@ -6,7 +6,7 @@ import java.net.Socket; | @@ -6,7 +6,7 @@ import java.net.Socket; | ||
| 6 | public class TCPServer { | 6 | public class TCPServer { |
| 7 | public static void main(String[] args) throws Exception{ | 7 | public static void main(String[] args) throws Exception{ |
| 8 | //创建socket,并将socket绑定到65000端口 | 8 | //创建socket,并将socket绑定到65000端口 |
| 9 | - ServerSocket ss = new ServerSocket(30020); | 9 | + ServerSocket ss = new ServerSocket(30000); |
| 10 | //死循环,使得socket一直等待并处理客户端发送过来的请求 | 10 | //死循环,使得socket一直等待并处理客户端发送过来的请求 |
| 11 | while(true){ | 11 | while(true){ |
| 12 | //监听65000端口,直到客户端返回连接信息后才返回 | 12 | //监听65000端口,直到客户端返回连接信息后才返回 |
src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
| @@ -60,7 +60,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | @@ -60,7 +60,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | ||
| 60 | @Autowired | 60 | @Autowired |
| 61 | private JwtAuthenticationFilter jwtAuthenticationFilter; | 61 | private JwtAuthenticationFilter jwtAuthenticationFilter; |
| 62 | 62 | ||
| 63 | - public static final List<String> ALLOWED_IPS = Arrays.asList("192.169.1.88", "127.0.0.1"); | 63 | + public static final List<String> ALLOWED_IPS = Arrays.asList("192.169.1.97", "127.0.0.1"); |
| 64 | 64 | ||
| 65 | 65 | ||
| 66 | /** | 66 | /** |
src/main/java/com/genersoft/iot/vmp/jtt1078/app/VideoServerApp.java
| 1 | package com.genersoft.iot.vmp.jtt1078.app; | 1 | package com.genersoft.iot.vmp.jtt1078.app; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.ConcurrentHashSet; | ||
| 3 | import com.genersoft.iot.vmp.jtt1078.http.GeneralResponseWriter; | 4 | import com.genersoft.iot.vmp.jtt1078.http.GeneralResponseWriter; |
| 4 | import com.genersoft.iot.vmp.jtt1078.http.NettyHttpServerHandler; | 5 | import com.genersoft.iot.vmp.jtt1078.http.NettyHttpServerHandler; |
| 5 | import com.genersoft.iot.vmp.jtt1078.publisher.PublishManager; | 6 | import com.genersoft.iot.vmp.jtt1078.publisher.PublishManager; |
| @@ -7,7 +8,6 @@ import com.genersoft.iot.vmp.jtt1078.server.Jtt1078Handler; | @@ -7,7 +8,6 @@ import com.genersoft.iot.vmp.jtt1078.server.Jtt1078Handler; | ||
| 7 | import com.genersoft.iot.vmp.jtt1078.server.Jtt1078MessageDecoder; | 8 | import com.genersoft.iot.vmp.jtt1078.server.Jtt1078MessageDecoder; |
| 8 | import com.genersoft.iot.vmp.jtt1078.server.SessionManager; | 9 | import com.genersoft.iot.vmp.jtt1078.server.SessionManager; |
| 9 | import com.genersoft.iot.vmp.jtt1078.util.Configs; | 10 | import com.genersoft.iot.vmp.jtt1078.util.Configs; |
| 10 | -import com.xiaoleilu.hutool.collection.ConcurrentHashSet; | ||
| 11 | import io.netty.bootstrap.ServerBootstrap; | 11 | import io.netty.bootstrap.ServerBootstrap; |
| 12 | import io.netty.channel.*; | 12 | import io.netty.channel.*; |
| 13 | import io.netty.channel.nio.NioEventLoopGroup; | 13 | import io.netty.channel.nio.NioEventLoopGroup; |
src/main/java/com/genersoft/iot/vmp/jtt1078/server/Jtt1078Handler.java
| @@ -17,7 +17,10 @@ import org.springframework.context.ApplicationContext; | @@ -17,7 +17,10 @@ import org.springframework.context.ApplicationContext; | ||
| 17 | import org.springframework.data.redis.core.StringRedisTemplate; | 17 | import org.springframework.data.redis.core.StringRedisTemplate; |
| 18 | 18 | ||
| 19 | import java.math.BigDecimal; | 19 | import java.math.BigDecimal; |
| 20 | +import java.text.SimpleDateFormat; | ||
| 21 | +import java.util.Date; | ||
| 20 | import java.util.Set; | 22 | import java.util.Set; |
| 23 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 21 | import java.util.concurrent.TimeUnit; | 24 | import java.util.concurrent.TimeUnit; |
| 22 | 25 | ||
| 23 | import static com.genersoft.iot.vmp.VManageBootstrap.getBean; | 26 | import static com.genersoft.iot.vmp.VManageBootstrap.getBean; |
| @@ -25,13 +28,18 @@ import static com.genersoft.iot.vmp.VManageBootstrap.getBean; | @@ -25,13 +28,18 @@ import static com.genersoft.iot.vmp.VManageBootstrap.getBean; | ||
| 25 | /** | 28 | /** |
| 26 | * Created by matrixy on 2019/4/9. | 29 | * Created by matrixy on 2019/4/9. |
| 27 | */ | 30 | */ |
| 28 | -public class Jtt1078Handler extends SimpleChannelInboundHandler<Packet> | ||
| 29 | -{ | 31 | +public class Jtt1078Handler extends SimpleChannelInboundHandler<Packet> { |
| 30 | private static ApplicationContext applicationContext; | 32 | private static ApplicationContext applicationContext; |
| 31 | static Logger logger = LoggerFactory.getLogger(Jtt1078Handler.class); | 33 | static Logger logger = LoggerFactory.getLogger(Jtt1078Handler.class); |
| 32 | private static final AttributeKey<Session> SESSION_KEY = AttributeKey.valueOf("session-key"); | 34 | private static final AttributeKey<Session> SESSION_KEY = AttributeKey.valueOf("session-key"); |
| 33 | private Integer port; | 35 | private Integer port; |
| 34 | 36 | ||
| 37 | + private String time; | ||
| 38 | + | ||
| 39 | + private static final DataBuffer simFlowDataBuffer = getBean(DataBuffer.class); | ||
| 40 | + | ||
| 41 | + private static final ConcurrentHashMap<String, SimFlow> sizeMap = new ConcurrentHashMap<>(); | ||
| 42 | + | ||
| 35 | public Jtt1078Handler(Integer port) { | 43 | public Jtt1078Handler(Integer port) { |
| 36 | this.port = port; | 44 | this.port = port; |
| 37 | } | 45 | } |
| @@ -43,37 +51,51 @@ public class Jtt1078Handler extends SimpleChannelInboundHandler<Packet> | @@ -43,37 +51,51 @@ public class Jtt1078Handler extends SimpleChannelInboundHandler<Packet> | ||
| 43 | * 流来 | 51 | * 流来 |
| 44 | */ | 52 | */ |
| 45 | @Override | 53 | @Override |
| 46 | - protected void channelRead0(ChannelHandlerContext ctx, Packet packet) throws Exception | ||
| 47 | - { | 54 | + protected void channelRead0(ChannelHandlerContext ctx, Packet packet) throws Exception { |
| 48 | io.netty.channel.Channel nettyChannel = ctx.channel(); | 55 | io.netty.channel.Channel nettyChannel = ctx.channel(); |
| 49 | packet.seek(8); | 56 | packet.seek(8); |
| 50 | String sim = packet.nextBCD() + packet.nextBCD() + packet.nextBCD() + packet.nextBCD() + packet.nextBCD() + packet.nextBCD(); | 57 | String sim = packet.nextBCD() + packet.nextBCD() + packet.nextBCD() + packet.nextBCD() + packet.nextBCD() + packet.nextBCD(); |
| 51 | int channel = packet.nextByte() & 0xff; | 58 | int channel = packet.nextByte() & 0xff; |
| 52 | String tag = sim + "-" + channel; | 59 | String tag = sim + "-" + channel; |
| 53 | tag = tag.replaceAll("^0+", ""); | 60 | tag = tag.replaceAll("^0+", ""); |
| 54 | - if (port != null){ | 61 | + if (port != null) { |
| 55 | Set<String> set = Jt1078OfCarController.map.get(port); | 62 | Set<String> set = Jt1078OfCarController.map.get(port); |
| 56 | String findSet = Jt1078OfCarController.getFindSet(set, tag); | 63 | String findSet = Jt1078OfCarController.getFindSet(set, tag); |
| 57 | - if (findSet != null){ | 64 | + if (findSet != null) { |
| 58 | tag = findSet + "_" + port; | 65 | tag = findSet + "_" + port; |
| 59 | - }else { | 66 | + } else { |
| 60 | return; | 67 | return; |
| 61 | } | 68 | } |
| 62 | } | 69 | } |
| 63 | StringRedisTemplate redisTemplate = getBean(StringRedisTemplate.class); | 70 | StringRedisTemplate redisTemplate = getBean(StringRedisTemplate.class); |
| 64 | - if (redisTemplate.opsForSet().add("tag:" + tag, tag) > 0){ | 71 | + if (redisTemplate.opsForSet().add("tag:" + tag, tag) > 0) { |
| 65 | redisTemplate.expire("tag:" + tag, 60, TimeUnit.SECONDS); | 72 | redisTemplate.expire("tag:" + tag, 60, TimeUnit.SECONDS); |
| 66 | - logger.info("[ {} ] --> 流接收成功 ",tag); | ||
| 67 | - }else { | 73 | + logger.info("[ {} ] --> 流接收成功 ", tag); |
| 74 | + } else { | ||
| 68 | redisTemplate.expire("tag:" + tag, 60, TimeUnit.SECONDS); | 75 | redisTemplate.expire("tag:" + tag, 60, TimeUnit.SECONDS); |
| 69 | } | 76 | } |
| 70 | - double num = new BigDecimal(packet.size()).divide(new BigDecimal(1024 * 1024 * 1024), 10, BigDecimal.ROUND_HALF_UP).doubleValue(); | ||
| 71 | - DataBuffer simFlowDataBuffer = getBean(DataBuffer.class); | ||
| 72 | - if (simFlowDataBuffer != null) { | ||
| 73 | - simFlowDataBuffer.setValue(SimFlow.build(sim,String.valueOf(channel),num)); | 77 | + String format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); |
| 78 | + | ||
| 79 | + String key = sim + "-" + channel; | ||
| 80 | + if (sizeMap.containsKey(key)){ | ||
| 81 | + SimFlow simFlow = sizeMap.get(key); | ||
| 82 | + simFlow.setFlow(simFlow.getFlow() + packet.size()); | ||
| 83 | + simFlow.setCount(simFlow.getCount() + 1); | ||
| 84 | + }else { | ||
| 85 | + sizeMap.put(key, SimFlow.builder().sim(sim).count(1).flow((long) packet.size()).channel(channel).time(format).build()); | ||
| 74 | } | 86 | } |
| 75 | - if (SessionManager.contains(nettyChannel, "tag") == false) | ||
| 76 | - { | 87 | + if (time == null || !time.equals(format)) { |
| 88 | + time = format; | ||
| 89 | + sizeMap.entrySet().forEach(entry -> { | ||
| 90 | + SimFlow value = entry.getValue(); | ||
| 91 | + logger.debug("{} === {}次 === {} 流来的大小 {} ", value.getTime(), value.getCount(), value.getSim() + "-" + value.getChannel(), value.getFlow()); | ||
| 92 | + if (simFlowDataBuffer != null) { | ||
| 93 | + simFlowDataBuffer.setValue(value); | ||
| 94 | + } | ||
| 95 | + }); | ||
| 96 | + sizeMap.clear(); | ||
| 97 | + } | ||
| 98 | + if (SessionManager.contains(nettyChannel, "tag") == false) { | ||
| 77 | Channel chl = PublishManager.getInstance().open(tag); | 99 | Channel chl = PublishManager.getInstance().open(tag); |
| 78 | SessionManager.set(nettyChannel, "tag", tag); | 100 | SessionManager.set(nettyChannel, "tag", tag); |
| 79 | logger.info("start publishing: {} -> {}-{}", Long.toHexString(chl.hashCode() & 0xffffffffL), sim, channel); | 101 | logger.info("start publishing: {} -> {}-{}", Long.toHexString(chl.hashCode() & 0xffffffffL), sim, channel); |
| @@ -92,19 +114,15 @@ public class Jtt1078Handler extends SimpleChannelInboundHandler<Packet> | @@ -92,19 +114,15 @@ public class Jtt1078Handler extends SimpleChannelInboundHandler<Packet> | ||
| 92 | 114 | ||
| 93 | int pt = packet.seek(5).nextByte() & 0x7f; | 115 | int pt = packet.seek(5).nextByte() & 0x7f; |
| 94 | 116 | ||
| 95 | - if (dataType == 0x00 || dataType == 0x01 || dataType == 0x02) | ||
| 96 | - { | 117 | + if (dataType == 0x00 || dataType == 0x01 || dataType == 0x02) { |
| 97 | // 碰到结束标记时,序号+1 | 118 | // 碰到结束标记时,序号+1 |
| 98 | - if (pkType == 0 || pkType == 2) | ||
| 99 | - { | 119 | + if (pkType == 0 || pkType == 2) { |
| 100 | sequence += 1; | 120 | sequence += 1; |
| 101 | SessionManager.set(nettyChannel, "video-sequence", sequence); | 121 | SessionManager.set(nettyChannel, "video-sequence", sequence); |
| 102 | } | 122 | } |
| 103 | long timestamp = packet.seek(16).nextLong(); | 123 | long timestamp = packet.seek(16).nextLong(); |
| 104 | PublishManager.getInstance().publishVideo(tag, sequence, timestamp, pt, packet.seek(lengthOffset + 2).nextBytes()); | 124 | PublishManager.getInstance().publishVideo(tag, sequence, timestamp, pt, packet.seek(lengthOffset + 2).nextBytes()); |
| 105 | - } | ||
| 106 | - else if (dataType == 0x03) | ||
| 107 | - { | 125 | + } else if (dataType == 0x03) { |
| 108 | long timestamp = packet.seek(16).nextLong(); | 126 | long timestamp = packet.seek(16).nextLong(); |
| 109 | byte[] data = packet.seek(lengthOffset + 2).nextBytes(); | 127 | byte[] data = packet.seek(lengthOffset + 2).nextBytes(); |
| 110 | PublishManager.getInstance().publishAudio(tag, sequence, timestamp, pt, data); | 128 | PublishManager.getInstance().publishAudio(tag, sequence, timestamp, pt, data); |
| @@ -112,15 +130,13 @@ public class Jtt1078Handler extends SimpleChannelInboundHandler<Packet> | @@ -112,15 +130,13 @@ public class Jtt1078Handler extends SimpleChannelInboundHandler<Packet> | ||
| 112 | } | 130 | } |
| 113 | 131 | ||
| 114 | @Override | 132 | @Override |
| 115 | - public void channelInactive(ChannelHandlerContext ctx) throws Exception | ||
| 116 | - { | 133 | + public void channelInactive(ChannelHandlerContext ctx) throws Exception { |
| 117 | super.channelInactive(ctx); | 134 | super.channelInactive(ctx); |
| 118 | release(ctx.channel()); | 135 | release(ctx.channel()); |
| 119 | } | 136 | } |
| 120 | 137 | ||
| 121 | @Override | 138 | @Override |
| 122 | - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception | ||
| 123 | - { | 139 | + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { |
| 124 | // super.exceptionCaught(ctx, cause); | 140 | // super.exceptionCaught(ctx, cause); |
| 125 | cause.printStackTrace(); | 141 | cause.printStackTrace(); |
| 126 | release(ctx.channel()); | 142 | release(ctx.channel()); |
| @@ -133,17 +149,15 @@ public class Jtt1078Handler extends SimpleChannelInboundHandler<Packet> | @@ -133,17 +149,15 @@ public class Jtt1078Handler extends SimpleChannelInboundHandler<Packet> | ||
| 133 | IdleStateEvent event = (IdleStateEvent) evt; | 149 | IdleStateEvent event = (IdleStateEvent) evt; |
| 134 | if (event.state() == IdleState.READER_IDLE) { | 150 | if (event.state() == IdleState.READER_IDLE) { |
| 135 | String tag = SessionManager.get(ctx.channel(), "tag"); | 151 | String tag = SessionManager.get(ctx.channel(), "tag"); |
| 136 | - logger.info("read timeout: {}",tag); | 152 | + logger.info("read timeout: {}", tag); |
| 137 | release(ctx.channel()); | 153 | release(ctx.channel()); |
| 138 | } | 154 | } |
| 139 | } | 155 | } |
| 140 | } | 156 | } |
| 141 | 157 | ||
| 142 | - private void release(io.netty.channel.Channel channel) | ||
| 143 | - { | 158 | + private void release(io.netty.channel.Channel channel) { |
| 144 | String tag = SessionManager.get(channel, "tag"); | 159 | String tag = SessionManager.get(channel, "tag"); |
| 145 | - if (tag != null) | ||
| 146 | - { | 160 | + if (tag != null) { |
| 147 | logger.info("close netty channel: {}", tag); | 161 | logger.info("close netty channel: {}", tag); |
| 148 | PublishManager.getInstance().close(tag); | 162 | PublishManager.getInstance().close(tag); |
| 149 | } | 163 | } |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/Jt1078OfCarController.java
| @@ -12,6 +12,8 @@ import com.alibaba.fastjson2.JSONObject; | @@ -12,6 +12,8 @@ import com.alibaba.fastjson2.JSONObject; | ||
| 12 | import com.genersoft.iot.vmp.conf.MediaConfig; | 12 | import com.genersoft.iot.vmp.conf.MediaConfig; |
| 13 | import com.genersoft.iot.vmp.conf.StreamProxyTask; | 13 | import com.genersoft.iot.vmp.conf.StreamProxyTask; |
| 14 | import com.genersoft.iot.vmp.conf.exception.ControllerException; | 14 | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| 15 | +import com.genersoft.iot.vmp.conf.security.JwtUtils; | ||
| 16 | +import com.genersoft.iot.vmp.conf.security.dto.JwtUser; | ||
| 15 | import com.genersoft.iot.vmp.jtt1078.app.VideoServerApp; | 17 | import com.genersoft.iot.vmp.jtt1078.app.VideoServerApp; |
| 16 | import com.genersoft.iot.vmp.jtt1078.publisher.PublishManager; | 18 | import com.genersoft.iot.vmp.jtt1078.publisher.PublishManager; |
| 17 | import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; | 19 | import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; |
| @@ -26,7 +28,6 @@ import com.genersoft.iot.vmp.vmanager.jt1078.platform.config.Jt1078ConfigBean; | @@ -26,7 +28,6 @@ import com.genersoft.iot.vmp.vmanager.jt1078.platform.config.Jt1078ConfigBean; | ||
| 26 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.config.RtspConfigBean; | 28 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.config.RtspConfigBean; |
| 27 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.config.TuohuaConfigBean; | 29 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.config.TuohuaConfigBean; |
| 28 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.domain.PatrolDataReq; | 30 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.domain.PatrolDataReq; |
| 29 | -import com.genersoft.iot.vmp.vmanager.jt1078.platform.domain.SimFlow; | ||
| 30 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.handler.HttpClientUtil; | 31 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.handler.HttpClientUtil; |
| 31 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.service.FlowService; | 32 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.service.FlowService; |
| 32 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.service.Jt1078OfService; | 33 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.service.Jt1078OfService; |
| @@ -43,10 +44,7 @@ import org.slf4j.Logger; | @@ -43,10 +44,7 @@ import org.slf4j.Logger; | ||
| 43 | import org.slf4j.LoggerFactory; | 44 | import org.slf4j.LoggerFactory; |
| 44 | import org.springframework.beans.factory.annotation.Autowired; | 45 | import org.springframework.beans.factory.annotation.Autowired; |
| 45 | import org.springframework.beans.factory.annotation.Value; | 46 | import org.springframework.beans.factory.annotation.Value; |
| 46 | -import org.springframework.data.redis.core.Cursor; | ||
| 47 | -import org.springframework.data.redis.core.RedisCallback; | ||
| 48 | import org.springframework.data.redis.core.RedisTemplate; | 47 | import org.springframework.data.redis.core.RedisTemplate; |
| 49 | -import org.springframework.data.redis.core.ScanOptions; | ||
| 50 | import org.springframework.util.Base64Utils; | 48 | import org.springframework.util.Base64Utils; |
| 51 | import org.springframework.web.bind.annotation.*; | 49 | import org.springframework.web.bind.annotation.*; |
| 52 | import sun.misc.Signal; | 50 | import sun.misc.Signal; |
| @@ -54,6 +52,7 @@ import sun.misc.SignalHandler; | @@ -54,6 +52,7 @@ import sun.misc.SignalHandler; | ||
| 54 | 52 | ||
| 55 | import javax.annotation.Resource; | 53 | import javax.annotation.Resource; |
| 56 | import javax.crypto.Cipher; | 54 | import javax.crypto.Cipher; |
| 55 | +import javax.servlet.http.HttpServletRequest; | ||
| 57 | import javax.validation.constraints.NotBlank; | 56 | import javax.validation.constraints.NotBlank; |
| 58 | import java.io.ByteArrayOutputStream; | 57 | import java.io.ByteArrayOutputStream; |
| 59 | import java.io.IOException; | 58 | import java.io.IOException; |
| @@ -109,7 +108,7 @@ public class Jt1078OfCarController { | @@ -109,7 +108,7 @@ public class Jt1078OfCarController { | ||
| 109 | //存储历史端口 key -->端口 value ---> sim-channel-startTime-endTime-port | 108 | //存储历史端口 key -->端口 value ---> sim-channel-startTime-endTime-port |
| 110 | public static final ConcurrentHashMap<Integer, Set<String>> map = new ConcurrentHashMap<>(); | 109 | public static final ConcurrentHashMap<Integer, Set<String>> map = new ConcurrentHashMap<>(); |
| 111 | 110 | ||
| 112 | - private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10,20,40,TimeUnit.SECONDS,new ArrayBlockingQueue<>(10)); | 111 | + private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20, 40, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10)); |
| 113 | 112 | ||
| 114 | @Value("${spring.profiles.active}") | 113 | @Value("${spring.profiles.active}") |
| 115 | private String profilesActive; | 114 | private String profilesActive; |
| @@ -118,11 +117,6 @@ public class Jt1078OfCarController { | @@ -118,11 +117,6 @@ public class Jt1078OfCarController { | ||
| 118 | public Jt1078OfCarController() { | 117 | public Jt1078OfCarController() { |
| 119 | } | 118 | } |
| 120 | 119 | ||
| 121 | - @GetMapping("/flow/countList/{timeType}/{statisticsType}/{time}") | ||
| 122 | - public Map<String, SimFlow> flowCountList(@PathVariable String statisticsType, @PathVariable String time, @PathVariable String timeType) { | ||
| 123 | - return flowService.getList(timeType, statisticsType, time); | ||
| 124 | - } | ||
| 125 | - | ||
| 126 | @GetMapping({"/company/tree"}) | 120 | @GetMapping({"/company/tree"}) |
| 127 | public Map<String, Object> requestTreeOfCompany() { | 121 | public Map<String, Object> requestTreeOfCompany() { |
| 128 | Map<String, Object> resultMap = new HashMap(); | 122 | Map<String, Object> resultMap = new HashMap(); |
| @@ -154,6 +148,7 @@ public class Jt1078OfCarController { | @@ -154,6 +148,7 @@ public class Jt1078OfCarController { | ||
| 154 | return resultMap; | 148 | return resultMap; |
| 155 | } | 149 | } |
| 156 | 150 | ||
| 151 | + | ||
| 157 | /** | 152 | /** |
| 158 | * redis清除在线车辆 | 153 | * redis清除在线车辆 |
| 159 | */ | 154 | */ |
| @@ -163,8 +158,10 @@ public class Jt1078OfCarController { | @@ -163,8 +158,10 @@ public class Jt1078OfCarController { | ||
| 163 | redisTemplate.delete(carId); | 158 | redisTemplate.delete(carId); |
| 164 | } | 159 | } |
| 165 | } | 160 | } |
| 161 | + | ||
| 166 | /** | 162 | /** |
| 167 | * redis存储在线车辆 | 163 | * redis存储在线车辆 |
| 164 | + * | ||
| 168 | * @param linesCars | 165 | * @param linesCars |
| 169 | */ | 166 | */ |
| 170 | public HashMap<String, Object> storageRedisTree(List<HashMap<String, Object>> linesCars) { | 167 | public HashMap<String, Object> storageRedisTree(List<HashMap<String, Object>> linesCars) { |
| @@ -214,6 +211,7 @@ public class Jt1078OfCarController { | @@ -214,6 +211,7 @@ public class Jt1078OfCarController { | ||
| 214 | 211 | ||
| 215 | /** | 212 | /** |
| 216 | * 请求设备推送流 | 213 | * 请求设备推送流 |
| 214 | + * | ||
| 217 | * @param sim sim号 | 215 | * @param sim sim号 |
| 218 | * @param channel 通道号 | 216 | * @param channel 通道号 |
| 219 | * @return | 217 | * @return |
| @@ -221,14 +219,14 @@ public class Jt1078OfCarController { | @@ -221,14 +219,14 @@ public class Jt1078OfCarController { | ||
| 221 | @GetMapping({"/send/request/io/{sim}/{channel}"}) | 219 | @GetMapping({"/send/request/io/{sim}/{channel}"}) |
| 222 | public StreamContent sendIORequest(@PathVariable String sim, @PathVariable String channel) { | 220 | public StreamContent sendIORequest(@PathVariable String sim, @PathVariable String channel) { |
| 223 | if (StringUtils.isBlank(sim)) { | 221 | if (StringUtils.isBlank(sim)) { |
| 224 | - throw new ControllerException(-100,"sim 不能为空"); | 222 | + throw new ControllerException(-100, "sim 不能为空"); |
| 225 | } | 223 | } |
| 226 | if (StringUtils.isBlank(channel)) { | 224 | if (StringUtils.isBlank(channel)) { |
| 227 | throw new ControllerException(-100, "channel 不能为空"); | 225 | throw new ControllerException(-100, "channel 不能为空"); |
| 228 | } | 226 | } |
| 229 | String stream = StringUtils.join(new String[]{sim, "-", channel}); | 227 | String stream = StringUtils.join(new String[]{sim, "-", channel}); |
| 230 | StreamContent streamContent = getStreamContentPlayURL(stream); | 228 | StreamContent streamContent = getStreamContentPlayURL(stream); |
| 231 | - if (Objects.isNull(streamContent) || StringUtils.isBlank(streamContent.getWs_flv())){ | 229 | + if (Objects.isNull(streamContent) || StringUtils.isBlank(streamContent.getWs_flv())) { |
| 232 | sendIORequest(stream); | 230 | sendIORequest(stream); |
| 233 | } | 231 | } |
| 234 | streamContent = getStreamContent(stream); | 232 | streamContent = getStreamContent(stream); |
| @@ -239,6 +237,7 @@ public class Jt1078OfCarController { | @@ -239,6 +237,7 @@ public class Jt1078OfCarController { | ||
| 239 | 237 | ||
| 240 | /** | 238 | /** |
| 241 | * 批量请求设备推送流 | 239 | * 批量请求设备推送流 |
| 240 | + * | ||
| 242 | * @param streamList 流唯一值集合 {sim-channel} | 241 | * @param streamList 流唯一值集合 {sim-channel} |
| 243 | */ | 242 | */ |
| 244 | @PostMapping({"/beachSend/request/io"}) | 243 | @PostMapping({"/beachSend/request/io"}) |
| @@ -256,6 +255,7 @@ public class Jt1078OfCarController { | @@ -256,6 +255,7 @@ public class Jt1078OfCarController { | ||
| 256 | 255 | ||
| 257 | /** | 256 | /** |
| 258 | * 视频巡查功能开启 | 257 | * 视频巡查功能开启 |
| 258 | + * | ||
| 259 | * @param PatrolDataReqList 视频巡查请求对象 | 259 | * @param PatrolDataReqList 视频巡查请求对象 |
| 260 | */ | 260 | */ |
| 261 | @PostMapping({"/startPatrol/request/io"}) | 261 | @PostMapping({"/startPatrol/request/io"}) |
| @@ -278,13 +278,14 @@ public class Jt1078OfCarController { | @@ -278,13 +278,14 @@ public class Jt1078OfCarController { | ||
| 278 | * 关闭视频巡查 (必须在关闭按钮后关闭,否则流量在一直消耗) | 278 | * 关闭视频巡查 (必须在关闭按钮后关闭,否则流量在一直消耗) |
| 279 | */ | 279 | */ |
| 280 | @GetMapping("/stopPatrol/request/io") | 280 | @GetMapping("/stopPatrol/request/io") |
| 281 | - public void stopPatrol(){ | 281 | + public void stopPatrol() { |
| 282 | Set<Object> keys = redisTemplate.keys("patrol:stream:*"); | 282 | Set<Object> keys = redisTemplate.keys("patrol:stream:*"); |
| 283 | redisTemplate.delete(keys); | 283 | redisTemplate.delete(keys); |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | /** | 286 | /** |
| 287 | * 获取播放地址对外接口 | 287 | * 获取播放地址对外接口 |
| 288 | + * | ||
| 288 | * @param sim | 289 | * @param sim |
| 289 | * @param channel | 290 | * @param channel |
| 290 | * @return | 291 | * @return |
| @@ -292,7 +293,7 @@ public class Jt1078OfCarController { | @@ -292,7 +293,7 @@ public class Jt1078OfCarController { | ||
| 292 | @PostMapping("/send/request/getPlay") | 293 | @PostMapping("/send/request/getPlay") |
| 293 | public Object sendGetPlay(@RequestParam String sim, @RequestParam String channel) { | 294 | public Object sendGetPlay(@RequestParam String sim, @RequestParam String channel) { |
| 294 | if (StringUtils.isBlank(sim)) { | 295 | if (StringUtils.isBlank(sim)) { |
| 295 | - throw new ControllerException(-100,"sim 不能为空"); | 296 | + throw new ControllerException(-100, "sim 不能为空"); |
| 296 | } | 297 | } |
| 297 | if (StringUtils.isBlank(channel)) { | 298 | if (StringUtils.isBlank(channel)) { |
| 298 | throw new ControllerException(-100, "channel 不能为空"); | 299 | throw new ControllerException(-100, "channel 不能为空"); |
| @@ -302,21 +303,21 @@ public class Jt1078OfCarController { | @@ -302,21 +303,21 @@ public class Jt1078OfCarController { | ||
| 302 | StreamPushItem streamPushItem = streamPushController.getStreamPushItem(sim, channel); | 303 | StreamPushItem streamPushItem = streamPushController.getStreamPushItem(sim, channel); |
| 303 | StreamContent playUrl = null; | 304 | StreamContent playUrl = null; |
| 304 | if (null != streamPushItem) { | 305 | if (null != streamPushItem) { |
| 305 | - playUrl = streamPushController.getPlayUrl(streamPushItem.getApp(), stream, streamPushItem.getMediaServerId()); | ||
| 306 | - if (playUrl != null){ | ||
| 307 | - return StreamPlayPath.build(playUrl,stream); | 306 | + playUrl = streamPushController.getPlayUrl(streamPushItem.getApp(), stream, streamPushItem.getMediaServerId()); |
| 307 | + if (playUrl != null) { | ||
| 308 | + return StreamPlayPath.build(playUrl, stream); | ||
| 308 | } | 309 | } |
| 309 | } | 310 | } |
| 310 | HashMap<String, Object> resultMap = new HashMap<>(); | 311 | HashMap<String, Object> resultMap = new HashMap<>(); |
| 311 | - sendIORequest(stream); | 312 | + sendIORequest(stream); |
| 312 | try { | 313 | try { |
| 313 | Thread.sleep(4000); | 314 | Thread.sleep(4000); |
| 314 | } catch (InterruptedException e) { | 315 | } catch (InterruptedException e) { |
| 315 | throw new RuntimeException(e); | 316 | throw new RuntimeException(e); |
| 316 | } | 317 | } |
| 317 | - if (map.get("code").equals("1")){ | 318 | + if (map.get("code").equals("1")) { |
| 318 | 319 | ||
| 319 | - while (true){ | 320 | + while (true) { |
| 320 | streamPushItem = streamPushController.getStreamPushItem(sim, channel); | 321 | streamPushItem = streamPushController.getStreamPushItem(sim, channel); |
| 321 | if (null == streamPushItem) { | 322 | if (null == streamPushItem) { |
| 322 | try { | 323 | try { |
| @@ -327,7 +328,7 @@ public class Jt1078OfCarController { | @@ -327,7 +328,7 @@ public class Jt1078OfCarController { | ||
| 327 | continue; | 328 | continue; |
| 328 | } | 329 | } |
| 329 | playUrl = streamPushController.getPlayUrl(streamPushItem.getApp(), stream, streamPushItem.getMediaServerId()); | 330 | playUrl = streamPushController.getPlayUrl(streamPushItem.getApp(), stream, streamPushItem.getMediaServerId()); |
| 330 | - if (playUrl == null){ | 331 | + if (playUrl == null) { |
| 331 | try { | 332 | try { |
| 332 | Thread.sleep(1000); | 333 | Thread.sleep(1000); |
| 333 | } catch (InterruptedException e) { | 334 | } catch (InterruptedException e) { |
| @@ -335,7 +336,7 @@ public class Jt1078OfCarController { | @@ -335,7 +336,7 @@ public class Jt1078OfCarController { | ||
| 335 | } | 336 | } |
| 336 | continue; | 337 | continue; |
| 337 | } | 338 | } |
| 338 | - return StreamPlayPath.build(playUrl,stream); | 339 | + return StreamPlayPath.build(playUrl, stream); |
| 339 | } | 340 | } |
| 340 | } | 341 | } |
| 341 | throw new RuntimeException("获取视频失败"); | 342 | throw new RuntimeException("获取视频失败"); |
| @@ -344,7 +345,8 @@ public class Jt1078OfCarController { | @@ -344,7 +345,8 @@ public class Jt1078OfCarController { | ||
| 344 | 345 | ||
| 345 | /** | 346 | /** |
| 346 | * 请求设备开始推流 | 347 | * 请求设备开始推流 |
| 347 | - * @param stream 流唯一标识 | 348 | + * |
| 349 | + * @param stream 流唯一标识 | ||
| 348 | */ | 350 | */ |
| 349 | public void sendIORequest(String stream) { | 351 | public void sendIORequest(String stream) { |
| 350 | 352 | ||
| @@ -373,7 +375,7 @@ public class Jt1078OfCarController { | @@ -373,7 +375,7 @@ public class Jt1078OfCarController { | ||
| 373 | HttpClientPostEntity entity1 = httpClientUtil.doPost(url, msg, jsessionid); | 375 | HttpClientPostEntity entity1 = httpClientUtil.doPost(url, msg, jsessionid); |
| 374 | chooseEntity(entity1, url, false); | 376 | chooseEntity(entity1, url, false); |
| 375 | log.info("发送[ {} ]推流指令成功 ===》 {}", stream, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); | 377 | log.info("发送[ {} ]推流指令成功 ===》 {}", stream, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); |
| 376 | - } catch (Exception e) { | 378 | + } catch (Exception e) { |
| 377 | log.error("发送推流指令异常;[{}], [{}], [{}]", url, msg, e.getMessage()); | 379 | log.error("发送推流指令异常;[{}], [{}], [{}]", url, msg, e.getMessage()); |
| 378 | throw new ControllerException(ErrorCode.ERROR420); | 380 | throw new ControllerException(ErrorCode.ERROR420); |
| 379 | } | 381 | } |
| @@ -667,11 +669,18 @@ public class Jt1078OfCarController { | @@ -667,11 +669,18 @@ public class Jt1078OfCarController { | ||
| 667 | @PathVariable @NotBlank(message = "channel 不能为空") String channel, | 669 | @PathVariable @NotBlank(message = "channel 不能为空") String channel, |
| 668 | @PathVariable @NotBlank(message = "开始时间不能为空") String startTime, | 670 | @PathVariable @NotBlank(message = "开始时间不能为空") String startTime, |
| 669 | @PathVariable @NotBlank(message = "结束时间不能为空") String endTime, | 671 | @PathVariable @NotBlank(message = "结束时间不能为空") String endTime, |
| 670 | - String channelMapping) { | 672 | + String channelMapping, HttpServletRequest request) { |
| 673 | + String header = request.getHeader("access-token"); | ||
| 674 | + JwtUser jwtUser = JwtUtils.verifyToken(header); | ||
| 675 | + String key = StringUtils.join(new String[]{"history:", sim, "-", channel}); | ||
| 676 | + Set<Object> keys = redisTemplate.keys(key + ":*"); | ||
| 677 | + String userKey = StringUtils.join(new String[]{key, ":", jwtUser.getUserName()}); | ||
| 678 | + if (CollectionUtils.isNotEmpty(keys) && !keys.contains(userKey)) { | ||
| 679 | + throw new ControllerException(400, "该通道被其他用户占用,请浏览其他通道"); | ||
| 680 | + } | ||
| 671 | Map<String, Object> resultMap = new HashMap(); | 681 | Map<String, Object> resultMap = new HashMap(); |
| 672 | startTime = this.formatTime(startTime); | 682 | startTime = this.formatTime(startTime); |
| 673 | endTime = this.formatTime(endTime); | 683 | endTime = this.formatTime(endTime); |
| 674 | - String key = StringUtils.join(new String[]{sim, "-", channel}); | ||
| 675 | channelMapping = StringUtils.join(new String[]{sim, "-", channel,"-",startTime,"-",endTime}); | 684 | channelMapping = StringUtils.join(new String[]{sim, "-", channel,"-",startTime,"-",endTime}); |
| 676 | Integer historyPort = createHistoryPort(channelMapping); | 685 | Integer historyPort = createHistoryPort(channelMapping); |
| 677 | channelMapping = StringUtils.join(new String[]{channelMapping,"_", String.valueOf(historyPort)}); | 686 | channelMapping = StringUtils.join(new String[]{channelMapping,"_", String.valueOf(historyPort)}); |
| @@ -703,7 +712,6 @@ public class Jt1078OfCarController { | @@ -703,7 +712,6 @@ public class Jt1078OfCarController { | ||
| 703 | this.redisTemplate.opsForValue().set("tag:history:httpPort:" + channelMapping, entity.getHttpPort(), 2L, TimeUnit.DAYS); | 712 | this.redisTemplate.opsForValue().set("tag:history:httpPort:" + channelMapping, entity.getHttpPort(), 2L, TimeUnit.DAYS); |
| 704 | this.redisTemplate.opsForValue().set("tag:history:httpPort:time:" + channelMapping, (new Date()).getTime(), StreamProxyTask.TIME_OUT, TimeUnit.SECONDS); | 713 | this.redisTemplate.opsForValue().set("tag:history:httpPort:time:" + channelMapping, (new Date()).getTime(), StreamProxyTask.TIME_OUT, TimeUnit.SECONDS); |
| 705 | msg = this.jt1078ConfigBean.formatMessageHistoryPlayRTSP(sim, channel, startTime, endTime, this.rtspConfigBean, entity.getPort()); | 714 | msg = this.jt1078ConfigBean.formatMessageHistoryPlayRTSP(sim, channel, startTime, endTime, this.rtspConfigBean, entity.getPort()); |
| 706 | - | ||
| 707 | HttpClientPostEntity entity1 = this.httpClientUtil.doPost(url, msg, (String) null); | 715 | HttpClientPostEntity entity1 = this.httpClientUtil.doPost(url, msg, (String) null); |
| 708 | chooseEntity(entity1, url, true); | 716 | chooseEntity(entity1, url, true); |
| 709 | resultMap.put("code", "1"); | 717 | resultMap.put("code", "1"); |
| @@ -712,7 +720,7 @@ public class Jt1078OfCarController { | @@ -712,7 +720,7 @@ public class Jt1078OfCarController { | ||
| 712 | resultMap.put("data", streamContent); | 720 | resultMap.put("data", streamContent); |
| 713 | return resultMap; | 721 | return resultMap; |
| 714 | } | 722 | } |
| 715 | - }catch (Exception e) { | 723 | + } catch (Exception e) { |
| 716 | log.error("发送推流指令异常;[{}], [{}], [{}]", url, msg, e.getMessage()); | 724 | log.error("发送推流指令异常;[{}], [{}], [{}]", url, msg, e.getMessage()); |
| 717 | throw new ControllerException(-20, "发送推流指令异常"); | 725 | throw new ControllerException(-20, "发送推流指令异常"); |
| 718 | } | 726 | } |
| @@ -721,7 +729,7 @@ public class Jt1078OfCarController { | @@ -721,7 +729,7 @@ public class Jt1078OfCarController { | ||
| 721 | /** | 729 | /** |
| 722 | * 从set<String>中找到对应唯一的sim-channel值 | 730 | * 从set<String>中找到对应唯一的sim-channel值 |
| 723 | */ | 731 | */ |
| 724 | - public static String getFindSet(Set<String> set,String targetString) { | 732 | + public static String getFindSet(Set<String> set, String targetString) { |
| 725 | for (String str : set) { | 733 | for (String str : set) { |
| 726 | if (str.startsWith(targetString)) { | 734 | if (str.startsWith(targetString)) { |
| 727 | return str; // 找到匹配项后立即返回 | 735 | return str; // 找到匹配项后立即返回 |
| @@ -729,6 +737,7 @@ public class Jt1078OfCarController { | @@ -729,6 +737,7 @@ public class Jt1078OfCarController { | ||
| 729 | } | 737 | } |
| 730 | return null; | 738 | return null; |
| 731 | } | 739 | } |
| 740 | + | ||
| 732 | /** | 741 | /** |
| 733 | * 从形如"sim-channel-start-end"的字符串中提取第二个'-'之前的值。 | 742 | * 从形如"sim-channel-start-end"的字符串中提取第二个'-'之前的值。 |
| 734 | */ | 743 | */ |
| @@ -749,6 +758,7 @@ public class Jt1078OfCarController { | @@ -749,6 +758,7 @@ public class Jt1078OfCarController { | ||
| 749 | return null; // 如果少于两个'-',则返回null | 758 | return null; // 如果少于两个'-',则返回null |
| 750 | } | 759 | } |
| 751 | } | 760 | } |
| 761 | + | ||
| 752 | /** | 762 | /** |
| 753 | * 遍历Map,寻找第一个不包含指定string的Set<String>, | 763 | * 遍历Map,寻找第一个不包含指定string的Set<String>, |
| 754 | * 将该string添加到Set中并返回对应的key,如果没有找到则返回null。 | 764 | * 将该string添加到Set中并返回对应的key,如果没有找到则返回null。 |
| @@ -757,7 +767,7 @@ public class Jt1078OfCarController { | @@ -757,7 +767,7 @@ public class Jt1078OfCarController { | ||
| 757 | // 使用entrySet()方法直接获取键值对进行迭代,效率更高 | 767 | // 使用entrySet()方法直接获取键值对进行迭代,效率更高 |
| 758 | for (Map.Entry<Integer, Set<String>> entry : map.entrySet()) { | 768 | for (Map.Entry<Integer, Set<String>> entry : map.entrySet()) { |
| 759 | Set<String> set = entry.getValue(); | 769 | Set<String> set = entry.getValue(); |
| 760 | - if (set.contains(targetString)){ | 770 | + if (set.contains(targetString)) { |
| 761 | return entry.getKey(); | 771 | return entry.getKey(); |
| 762 | } | 772 | } |
| 763 | // 如果当前Set不包含目标字符串,则添加并返回key | 773 | // 如果当前Set不包含目标字符串,则添加并返回key |
| @@ -766,8 +776,8 @@ public class Jt1078OfCarController { | @@ -766,8 +776,8 @@ public class Jt1078OfCarController { | ||
| 766 | set.add(targetString); | 776 | set.add(targetString); |
| 767 | if (secondDashValue != null && findSet == null) { | 777 | if (secondDashValue != null && findSet == null) { |
| 768 | return entry.getKey(); // 立即返回对应的key,不再继续查找 | 778 | return entry.getKey(); // 立即返回对应的key,不再继续查找 |
| 769 | - }else { | ||
| 770 | - clearMap(String.valueOf(entry.getKey()),findSet); | 779 | + } else { |
| 780 | + clearMap(String.valueOf(entry.getKey()), findSet); | ||
| 771 | } | 781 | } |
| 772 | } | 782 | } |
| 773 | return null; // 如果所有Set都包含目标字符串,则返回null | 783 | return null; // 如果所有Set都包含目标字符串,则返回null |
| @@ -776,7 +786,7 @@ public class Jt1078OfCarController { | @@ -776,7 +786,7 @@ public class Jt1078OfCarController { | ||
| 776 | /** | 786 | /** |
| 777 | * 清理map中的值 | 787 | * 清理map中的值 |
| 778 | */ | 788 | */ |
| 779 | - public void clearMap(String key,String value) { | 789 | + public void clearMap(String key, String value) { |
| 780 | if (StringUtils.isNotBlank(key) && StringUtils.isNotBlank(value)) { | 790 | if (StringUtils.isNotBlank(key) && StringUtils.isNotBlank(value)) { |
| 781 | Set<String> strings = map.get(Integer.valueOf(key)); | 791 | Set<String> strings = map.get(Integer.valueOf(key)); |
| 782 | if (strings == null) { | 792 | if (strings == null) { |
| @@ -790,48 +800,48 @@ public class Jt1078OfCarController { | @@ -790,48 +800,48 @@ public class Jt1078OfCarController { | ||
| 790 | throw new RuntimeException(e); | 800 | throw new RuntimeException(e); |
| 791 | } | 801 | } |
| 792 | String[] split = value.split("-"); | 802 | String[] split = value.split("-"); |
| 793 | - stopHistory(split[1],split[0]); | 803 | + stopHistory(split[1], split[0]); |
| 794 | strings.remove(value); | 804 | strings.remove(value); |
| 795 | } | 805 | } |
| 796 | - }else { | 806 | + } else { |
| 797 | log.error("清理端口缓存错误 !!!"); | 807 | log.error("清理端口缓存错误 !!!"); |
| 798 | } | 808 | } |
| 799 | } | 809 | } |
| 800 | 810 | ||
| 801 | /** | 811 | /** |
| 802 | * 创建历史端口 | 812 | * 创建历史端口 |
| 813 | + * | ||
| 803 | * @param key 通道唯一值 | 814 | * @param key 通道唯一值 |
| 804 | */ | 815 | */ |
| 805 | - public Integer createHistoryPort(String key){ | 816 | + public Integer createHistoryPort(String key) { |
| 806 | Integer port = addStringToFirstNonContainingSet(key); | 817 | Integer port = addStringToFirstNonContainingSet(key); |
| 807 | if (port == null) { | 818 | if (port == null) { |
| 808 | - throw new RuntimeException(String.format("[ %s ]通道观看人数太多,请等待 !!!",key)); | 819 | + throw new RuntimeException(String.format("[ %s ]通道观看人数太多,请等待 !!!", key)); |
| 809 | } | 820 | } |
| 810 | try { | 821 | try { |
| 811 | - if (redisTemplate.opsForValue().get("history:port:"+port) == null) { | 822 | + if (redisTemplate.opsForValue().get("history:port:" + port) == null) { |
| 812 | startPost(port); | 823 | startPost(port); |
| 813 | - redisTemplate.opsForValue().set("history:port:"+port, port); | 824 | + redisTemplate.opsForValue().set("history:port:" + port, port); |
| 814 | } | 825 | } |
| 815 | return port; | 826 | return port; |
| 816 | } catch (Exception e) { | 827 | } catch (Exception e) { |
| 817 | - log.error("{}",e.getMessage(),e); | 828 | + log.error("{}", e.getMessage(), e); |
| 818 | throw new RuntimeException(String.format("[ %s ]端口启动异常", port)); | 829 | throw new RuntimeException(String.format("[ %s ]端口启动异常", port)); |
| 819 | } | 830 | } |
| 820 | } | 831 | } |
| 821 | 832 | ||
| 822 | /** | 833 | /** |
| 823 | * 启动历史端口监听 | 834 | * 启动历史端口监听 |
| 835 | + * | ||
| 824 | * @param port 端口 | 836 | * @param port 端口 |
| 825 | */ | 837 | */ |
| 826 | private void startPost(Integer port) throws Exception { | 838 | private void startPost(Integer port) throws Exception { |
| 827 | VideoServerApp videoServerApp = new VideoServerApp(); | 839 | VideoServerApp videoServerApp = new VideoServerApp(); |
| 828 | 840 | ||
| 829 | VideoServerApp.VideoServer videoServer = videoServerApp.getVideoServer(port); | 841 | VideoServerApp.VideoServer videoServer = videoServerApp.getVideoServer(port); |
| 830 | - Signal.handle(new Signal("TERM"), new SignalHandler() | ||
| 831 | - { | 842 | + Signal.handle(new Signal("TERM"), new SignalHandler() { |
| 832 | @Override | 843 | @Override |
| 833 | - public void handle(Signal signal) | ||
| 834 | - { | 844 | + public void handle(Signal signal) { |
| 835 | videoServer.shutdown(); | 845 | videoServer.shutdown(); |
| 836 | } | 846 | } |
| 837 | }); | 847 | }); |
| @@ -840,7 +850,7 @@ public class Jt1078OfCarController { | @@ -840,7 +850,7 @@ public class Jt1078OfCarController { | ||
| 840 | 850 | ||
| 841 | 851 | ||
| 842 | @Nullable | 852 | @Nullable |
| 843 | - private StreamContent getStreamContent(String stream){ | 853 | + private StreamContent getStreamContent(String stream) { |
| 844 | 854 | ||
| 845 | StreamContent streamContent = this.getStreamContentPlayURL(stream); | 855 | StreamContent streamContent = this.getStreamContentPlayURL(stream); |
| 846 | if (Objects.isNull(streamContent) || StringUtils.isEmpty(streamContent.getWs_flv())) { | 856 | if (Objects.isNull(streamContent) || StringUtils.isEmpty(streamContent.getWs_flv())) { |
| @@ -863,8 +873,6 @@ public class Jt1078OfCarController { | @@ -863,8 +873,6 @@ public class Jt1078OfCarController { | ||
| 863 | * @return | 873 | * @return |
| 864 | */ | 874 | */ |
| 865 | private StreamContent requestStreamContent(int count, String stream, int httpPort) { | 875 | private StreamContent requestStreamContent(int count, String stream, int httpPort) { |
| 866 | - | ||
| 867 | - | ||
| 868 | StreamContent streamContent = this.getStreamContentPlayURL(stream); | 876 | StreamContent streamContent = this.getStreamContentPlayURL(stream); |
| 869 | return streamContent; | 877 | return streamContent; |
| 870 | } | 878 | } |
| @@ -975,35 +983,6 @@ public class Jt1078OfCarController { | @@ -975,35 +983,6 @@ public class Jt1078OfCarController { | ||
| 975 | } | 983 | } |
| 976 | 984 | ||
| 977 | /** | 985 | /** |
| 978 | - * 获取所有匹配模式 jt1078:server:port:* 的键,并找到其中剩余时间最短的键。 | ||
| 979 | - */ | ||
| 980 | - public String findKeyWithShortestTTL(String keyMatch) { | ||
| 981 | - String shortestTTLKey = null; | ||
| 982 | - long shortestTTL = Long.MAX_VALUE; | ||
| 983 | - // 使用 SCAN 命令遍历键空间 | ||
| 984 | - Cursor<byte[]> cursor = redisTemplate.execute( | ||
| 985 | - (RedisCallback<Cursor<byte[]>>) connection -> { | ||
| 986 | - ScanOptions options = ScanOptions.scanOptions().match(keyMatch).count(100).build(); | ||
| 987 | - return connection.scan(options); | ||
| 988 | - }); | ||
| 989 | - | ||
| 990 | - if (cursor != null) { | ||
| 991 | - while (cursor.hasNext()) { | ||
| 992 | - byte[] keyBytes = cursor.next(); | ||
| 993 | - String key = new String(keyBytes); | ||
| 994 | - | ||
| 995 | - // 获取当前键的 TTL | ||
| 996 | - Long ttl = redisTemplate.getExpire(key, TimeUnit.SECONDS); | ||
| 997 | - if (ttl != null && ttl >= 0 && ttl < shortestTTL) { | ||
| 998 | - shortestTTL = ttl; | ||
| 999 | - shortestTTLKey = key; | ||
| 1000 | - } | ||
| 1001 | - } | ||
| 1002 | - } | ||
| 1003 | - return shortestTTLKey; | ||
| 1004 | - } | ||
| 1005 | - | ||
| 1006 | - /** | ||
| 1007 | * 创建监听者 | 986 | * 创建监听者 |
| 1008 | * | 987 | * |
| 1009 | * @param channelMapping | 988 | * @param channelMapping |
| @@ -1040,13 +1019,13 @@ public class Jt1078OfCarController { | @@ -1040,13 +1019,13 @@ public class Jt1078OfCarController { | ||
| 1040 | 1019 | ||
| 1041 | if (flag) { | 1020 | if (flag) { |
| 1042 | if (StringUtils.isNoneBlank(new CharSequence[]{rsultMap.get("msg") + ""})) { | 1021 | if (StringUtils.isNoneBlank(new CharSequence[]{rsultMap.get("msg") + ""})) { |
| 1043 | - throw new ControllerException(304, String.valueOf(rsultMap.get("msg"))); | 1022 | + throw new ControllerException(304, String.valueOf(rsultMap.get("msg"))); |
| 1044 | } | 1023 | } |
| 1045 | } | 1024 | } |
| 1046 | } catch (Exception var6) { | 1025 | } catch (Exception var6) { |
| 1047 | Exception e = var6; | 1026 | Exception e = var6; |
| 1048 | - log.error("entity.getResultStr():{{}}", entity.getResultStr(), e.getMessage(), e); | ||
| 1049 | - throw new ControllerException(500,e.getMessage()); | 1027 | + log.error("entity.getResultStr():{{}}", entity.getResultStr(), e.getMessage()); |
| 1028 | + throw new ControllerException(500, e.getMessage()); | ||
| 1050 | } | 1029 | } |
| 1051 | } | 1030 | } |
| 1052 | } | 1031 | } |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/config/DataBuffer.java
| @@ -29,8 +29,12 @@ public class DataBuffer<T> { | @@ -29,8 +29,12 @@ public class DataBuffer<T> { | ||
| 29 | 29 | ||
| 30 | public List<T> getDataList(){ | 30 | public List<T> getDataList(){ |
| 31 | if (booleanValue.getAndSet(!booleanValue.get())){ | 31 | if (booleanValue.getAndSet(!booleanValue.get())){ |
| 32 | - return new ArrayList<>(trueQueue); | 32 | + ArrayList<T> list = new ArrayList<>(trueQueue); |
| 33 | + trueQueue.clear(); | ||
| 34 | + return list; | ||
| 33 | } | 35 | } |
| 34 | - return new ArrayList<>(falseQueue); | 36 | + ArrayList<T> list = new ArrayList<>(falseQueue); |
| 37 | + falseQueue.clear(); | ||
| 38 | + return list; | ||
| 35 | } | 39 | } |
| 36 | } | 40 | } |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/config/DataBufferConfig.java
| @@ -63,10 +63,10 @@ public class DataBufferConfig { | @@ -63,10 +63,10 @@ public class DataBufferConfig { | ||
| 63 | SimFlow simFlow = flowService.selectOne(value); | 63 | SimFlow simFlow = flowService.selectOne(value); |
| 64 | if (simFlow == null) { | 64 | if (simFlow == null) { |
| 65 | boolean b = flowService.addFlow(value); | 65 | boolean b = flowService.addFlow(value); |
| 66 | - log.info("流量信息添加 {} ",b?"成功":"失败"); | 66 | + log.debug("流量信息添加 {} ",b?"成功":"失败"); |
| 67 | }else { | 67 | }else { |
| 68 | boolean b = flowService.updateFlow(value); | 68 | boolean b = flowService.updateFlow(value); |
| 69 | - log.info("修改库中流量信息 {} ",b?"成功":"失败"); | 69 | + log.debug("修改库中流量信息 {} ",b?"成功":"失败"); |
| 70 | } | 70 | } |
| 71 | }); | 71 | }); |
| 72 | } | 72 | } |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/config/FtpConfigBean.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.vmanager.jt1078.platform.config; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | +import org.springframework.boot.context.properties.ConfigurationProperties; | ||
| 5 | +import org.springframework.context.annotation.Configuration; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * Ftp配置 | ||
| 9 | + * | ||
| 10 | + * @Author WangXin | ||
| 11 | + * @Data 2025/2/11 | ||
| 12 | + * @Version 1.0.0 | ||
| 13 | + */ | ||
| 14 | +@Data | ||
| 15 | +@Configuration | ||
| 16 | +@ConfigurationProperties(prefix = "ftp") | ||
| 17 | +public class FtpConfigBean { | ||
| 18 | + | ||
| 19 | + private String basePath; | ||
| 20 | + /** | ||
| 21 | + * ftp地址 | ||
| 22 | + */ | ||
| 23 | + private String host; | ||
| 24 | + private String httpPath; | ||
| 25 | + /** | ||
| 26 | + * | ||
| 27 | + */ | ||
| 28 | + private String filePathPrefix; | ||
| 29 | + /** | ||
| 30 | + * 密码 | ||
| 31 | + */ | ||
| 32 | + private String password; | ||
| 33 | + /** | ||
| 34 | + * 端口 | ||
| 35 | + */ | ||
| 36 | + private Integer port; | ||
| 37 | + /** | ||
| 38 | + * 用户名 | ||
| 39 | + */ | ||
| 40 | + private String username; | ||
| 41 | + /** | ||
| 42 | + * 失败重试次数 -1为一直重试 | ||
| 43 | + */ | ||
| 44 | + private Integer retryTimes; | ||
| 45 | + /** | ||
| 46 | + * 失败重试间隔时间 | ||
| 47 | + */ | ||
| 48 | + private Integer retryWaitTimes; | ||
| 49 | +} |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/config/Jt1078ConfigBean.java
| 1 | -package com.genersoft.iot.vmp.vmanager.jt1078.platform.config; import com.genersoft.iot.vmp.vmanager.jt1078.platform.Jt1078OfCarController; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.*; @Component public class Jt1078ConfigBean { @Value("${tuohua.bsth.jt1078.url}") private String jt1078Url; @Value("${tuohua.bsth.jt1078.sendPort}") private String jt1078SendPort; @Value("${tuohua.bsth.jt1078.stopSendPort}") private String stopSendPort; @Value("${tuohua.bsth.jt1078.historyListPort}") private String historyListPort; @Value("${tuohua.bsth.jt1078.playHistoryPort}") private String playHistoryPort; @Value("${tuohua.bsth.jt1078.ports}") private String portsOf1078; @Value("${tuohua.bsth.jt1078.pushURL}") private String pushURL; @Value("${tuohua.bsth.jt1078.stopPushURL}") private String stopPUshURL; private Integer start1078Port; private Integer end1078Port; @Value("${tuohua.bsth.jt1078.get.url}") private String getURL; @Value("${tuohua.bsth.jt1078.addPortVal}") private Integer addPort; @Value("${tuohua.bsth.jt1078.ws}") private String ws; @Value("${tuohua.bsth.jt1078.wss}") private String wss; @Value("${tuohua.bsth.jt1078.downloadFLV}") private String downloadFlv; @Value("${tuohua.bsth.jt1078.port}") private Integer port; @Value("${tuohua.bsth.jt1078.httpPort}") private Integer httpPort; @Value("${spring.profiles.active}") private String profilesActive; @Value("${media.pushKey}") private String pushKey; @Resource private RedisTemplate<String, Integer> redisTemplate; public Integer getPort() { if (port == null) { return 30000; } return port; } public Integer getHttpPort() { if (httpPort == null) { return 30000; } return httpPort; } private Integer getIntPort() { return profilesActive.equals("wx-local") ? 10000 : 0; } @PostConstruct public void initMap() { Set<String> historyPortKeys = redisTemplate.keys("history:port:*"); Set<String> keys = redisTemplate.keys("tag:*"); Set<String> patrolKeys = redisTemplate.keys("patrol:stream:*"); if (!historyPortKeys.isEmpty()) { keys.addAll(historyPortKeys); } if (!patrolKeys.isEmpty()) { keys.addAll(patrolKeys); } if (keys != null) { redisTemplate.delete(keys); } Map<Integer, Set<String>> hashMap = new HashMap<>(); for (int number = getStart1078Port(); number <= getEnd1078Port(); number++) { hashMap.put(number, new HashSet<>()); } Jt1078OfCarController.map.putAll(hashMap); } private static final String SEND_IO_MESSAGE_RTSP = "{ \"messageId\": 37121, \"properties\": 0, \"clientId\": \"{clientId}\", \"serialNo\": \"1\", \"ip\": \"{ip}\", \"tcpPort\": \"{tcpPort}\", \"udpPort\": \"{udpPort}\", \"channelNo\": \"{channelNo}\", \"mediaType\": \"1\", \"streamType\": \"1\"}"; private static final String SEND_IO_MESSAGE_RTSP_STOP = "{\"messageId\": 37122,\"properties\": 0,\"clientId\": \"{clientId}\",\"serialNo\": \"1\",\"channelNo\": \"{channelNo}\",\"command\": \"0\",\"closeType\": \"0\",\"streamType\": \"1\"}"; private static final String SEND_IO_HISTORY_RTSP = "{\"msgid\":37381,\"clientId\":\"{clientId}\",\"startTime\":\"{startTime}\",\"endTime\":\"{endTime}\",\"mediaType\":0,\"streamType\":0,\"storageType\":0,\"channelId\":{channelNo}}"; private static final String SEND_IO_PLAY_RTSP = "{\"ip\":\"{ip}\",\"tcpPort\":{tcpPort},\"udpPort\":{udpPort},\"channelNo\":\"{channelNo}\",\"mediaType\":0,\"streamType\":0,\"storageType\":0,\"playbackType\":0,\"playbackSpeed\":1,\"startTime\":\"{startTime}\",\"endTime\":\"{endTime}\",\"clientId\":\"{sim}\",\"messageId\":37377}"; public String formatMessageId(String sim, String channel, RtspConfigBean configBean, Integer port) { String msg = StringUtils.replace("{ \"messageId\": 37121, \"properties\": 0, \"clientId\": \"{clientId}\", \"serialNo\": \"1\", \"ip\": \"{ip}\", \"tcpPort\": \"{tcpPort}\", \"udpPort\": \"{udpPort}\", \"channelNo\": \"{channelNo}\", \"mediaType\": \"1\", \"streamType\": \"1\"}", "{clientId}", sim); msg = StringUtils.replace(msg, "{tcpPort}", (port.intValue() + getIntPort() + getAddPort()) + ""); msg = StringUtils.replace(msg, "{udpPort}", (port.intValue() + getIntPort() + getAddPort()) + ""); msg = StringUtils.replace(msg, "{channelNo}", channel); return StringUtils.replace(msg, "{ip}", configBean.getRtspIp()); } public String formatMessageStop(String sim, String channel) { String msg = StringUtils.replace("{\"messageId\": 37122,\"properties\": 0,\"clientId\": \"{clientId}\",\"serialNo\": \"1\",\"channelNo\": \"{channelNo}\",\"command\": \"0\",\"closeType\": \"0\",\"streamType\": \"1\"}", "{clientId}", sim); return StringUtils.replace(msg, "{channelNo}", channel); } public String formatMessageHistoryListRTSP(String sim, String channel, String startTime, String endTime) { String msg = StringUtils.replace("{\"msgid\":37381,\"clientId\":\"{clientId}\",\"startTime\":\"{startTime}\",\"endTime\":\"{endTime}\",\"mediaType\":0,\"streamType\":0,\"storageType\":0,\"channelId\":{channelNo}}", "{clientId}", sim); msg = StringUtils.replace(msg, "{startTime}", startTime); msg = StringUtils.replace(msg, "{endTime}", endTime); return StringUtils.replace(msg, "{channelNo}", channel); } public String formatMessageHistoryPlayRTSP(String sim, String channel, String startTime, String endTime, RtspConfigBean configBean, Integer port) { String msg = StringUtils.replace("{\"ip\":\"{ip}\",\"tcpPort\":{tcpPort},\"udpPort\":{udpPort},\"channelNo\":\"{channelNo}\",\"mediaType\":0,\"streamType\":0,\"storageType\":0,\"playbackType\":0,\"playbackSpeed\":1,\"startTime\":\"{startTime}\",\"endTime\":\"{endTime}\",\"clientId\":\"{sim}\",\"messageId\":37377}", "{clientId}", sim); msg = StringUtils.replace(msg, "{startTime}", startTime); msg = StringUtils.replace(msg, "{endTime}", endTime); msg = StringUtils.replace(msg, "{channelNo}", channel); msg = StringUtils.replace(msg, "{tcpPort}", (port.intValue() + getIntPort() +getAddPort()) + ""); msg = StringUtils.replace(msg, "{udpPort}", (port.intValue() + getIntPort() + getAddPort()) + ""); msg = StringUtils.replace(msg, "{sim}", sim); return StringUtils.replace(msg, "{ip}", configBean.getRtspIp()); } public String formatMessageHistoryStopRTSP(String sim, String channel, RtspConfigBean configBean) { String msg = StringUtils.replace("{\"playbackMode\":2,\"channelNo\":{channelNo},\"playbackSpeed\":0,\"clientId\":\"{sim}\"}", "{sim}", sim); return StringUtils.replace(msg, "{channelNo}", channel); } public String formatPushURL(String pushKey, int port, int httpPort) { String msg = StringUtils.replace(this.pushURL, "{pushKey}", pushKey); msg = StringUtils.replace(msg, "{port}", String.valueOf(port)); return StringUtils.replace(msg, "{httpPort}", String.valueOf(httpPort)); } public String formatStopPushURL(String pushKey, int port, int httpPort) { String msg = StringUtils.replace(this.stopPUshURL, "{pushKey}", pushKey); msg = StringUtils.replace(msg, "{port}", String.valueOf(port)); return StringUtils.replace(msg, "{httpPort}", String.valueOf(httpPort)); } public String formatVideoURL(String stream) { String url = StringUtils.replace(getGetURL(), "{stream}", stream); if (!StringUtils.endsWith(url, ".flv")) { url = url + ".flv"; } return url; } public String getJt1078Url() { return this.jt1078Url; } public String getJt1078SendPort() { return this.jt1078SendPort; } public String getStopSendPort() { return this.stopSendPort; } public String getHistoryListPort() { return this.historyListPort; } public String getPlayHistoryPort() { return this.playHistoryPort; } public String getPushURL() { return this.pushURL; } public Integer getStart1078Port() { if (Objects.isNull(this.start1078Port)) this.start1078Port = Integer.valueOf(Integer.parseInt(StringUtils.substringBefore(this.portsOf1078, ","))); return this.start1078Port; } public Integer getEnd1078Port() { if (Objects.isNull(this.end1078Port)) this.end1078Port = Integer.valueOf(Integer.parseInt(StringUtils.substringAfter(this.portsOf1078, ","))); return this.end1078Port; } public String getPushKey(){ if (Objects.isNull(this.pushKey)){ this.pushKey = "?callId=41db35390ddad33f83944f44b8b75ded"; } return "?callId="+this.pushKey; } public String getStopPUshURL() { return this.stopPUshURL; } public String getGetURL() { return this.getURL; } public Integer getAddPort() { return this.addPort; } public String getWs() { return this.ws; } public String getWss() { return this.wss; } public String getDownloadFlv() { return downloadFlv; } public String getPortsOf1078() { return portsOf1078; } } | ||
| 2 | \ No newline at end of file | 1 | \ No newline at end of file |
| 2 | +package com.genersoft.iot.vmp.vmanager.jt1078.platform.config; import com.genersoft.iot.vmp.vmanager.jt1078.platform.Jt1078OfCarController; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.*; @Component public class Jt1078ConfigBean { @Value("${tuohua.bsth.jt1078.url}") private String jt1078Url; @Value("${tuohua.bsth.jt1078.sendPort}") private String jt1078SendPort; @Value("${tuohua.bsth.jt1078.stopSendPort}") private String stopSendPort; @Value("${tuohua.bsth.jt1078.historyListPort}") private String historyListPort; @Value("${tuohua.bsth.jt1078.playHistoryPort}") private String playHistoryPort; @Value("${tuohua.bsth.jt1078.ports}") private String portsOf1078; @Value("${tuohua.bsth.jt1078.pushURL}") private String pushURL; @Value("${tuohua.bsth.jt1078.stopPushURL}") private String stopPUshURL; private Integer start1078Port; private Integer end1078Port; @Value("${tuohua.bsth.jt1078.get.url}") private String getURL; @Value("${tuohua.bsth.jt1078.addPortVal}") private Integer addPort; @Value("${tuohua.bsth.jt1078.ws}") private String ws; @Value("${tuohua.bsth.jt1078.wss}") private String wss; @Value("${tuohua.bsth.jt1078.downloadFLV}") private String downloadFlv; @Value("${tuohua.bsth.jt1078.port}") private Integer port; @Value("${tuohua.bsth.jt1078.httpPort}") private Integer httpPort; @Value("${spring.profiles.active}") private String profilesActive; @Value("${media.pushKey}") private String pushKey; @Resource private RedisTemplate<String, Integer> redisTemplate; public Integer getPort() { if (port == null) { return 30000; } return port; } public Integer getHttpPort() { if (httpPort == null) { return 30000; } return httpPort; } private Integer getIntPort() { return profilesActive.equals("wx-local") ? 10000 : 0; } @PostConstruct public void initMap() { Set<String> historyPortKeys = redisTemplate.keys("history:port:*"); Set<String> keys = redisTemplate.keys("tag:*"); Set<String> patrolKeys = redisTemplate.keys("patrol:stream:*"); if (!historyPortKeys.isEmpty()) { keys.addAll(historyPortKeys); } if (!patrolKeys.isEmpty()) { keys.addAll(patrolKeys); } if (keys != null) { redisTemplate.delete(keys); } Map<Integer, Set<String>> hashMap = new HashMap<>(); for (int number = getStart1078Port(); number <= getEnd1078Port(); number++) { hashMap.put(number, new HashSet<>()); } Jt1078OfCarController.map.putAll(hashMap); } private static final String SEND_IO_MESSAGE_RTSP = "{ \"messageId\": 37121, \"properties\": 0, \"clientId\": \"{clientId}\", \"serialNo\": \"1\", \"ip\": \"{ip}\", \"tcpPort\": \"{tcpPort}\", \"udpPort\": \"{udpPort}\", \"channelNo\": \"{channelNo}\", \"mediaType\": \"1\", \"streamType\": \"1\"}"; private static final String SEND_IO_MESSAGE_RTSP_STOP = "{\"messageId\": 37122,\"properties\": 0,\"clientId\": \"{clientId}\",\"serialNo\": \"1\",\"channelNo\": \"{channelNo}\",\"command\": \"0\",\"closeType\": \"0\",\"streamType\": \"1\"}"; private static final String SEND_IO_HISTORY_RTSP = "{\"msgid\":37381,\"clientId\":\"{clientId}\",\"startTime\":\"{startTime}\",\"endTime\":\"{endTime}\",\"mediaType\":0,\"streamType\":0,\"storageType\":0,\"channelId\":{channelNo}}"; private static final String SEND_IO_PLAY_RTSP = "{\"ip\":\"{ip}\",\"tcpPort\":{tcpPort},\"udpPort\":{udpPort},\"channelNo\":\"{channelNo}\",\"mediaType\":0,\"streamType\":0,\"storageType\":0,\"playbackType\":0,\"playbackSpeed\":1,\"startTime\":\"{startTime}\",\"endTime\":\"{endTime}\",\"clientId\":\"{sim}\",\"messageId\":37377}"; public String formatMessageId(String sim, String channel, RtspConfigBean configBean, Integer port) { String msg = StringUtils.replace("{ \"messageId\": 37121, \"properties\": 0, \"clientId\": \"{clientId}\", \"serialNo\": \"1\", \"ip\": \"{ip}\", \"tcpPort\": \"{tcpPort}\", \"udpPort\": \"{udpPort}\", \"channelNo\": \"{channelNo}\", \"mediaType\": \"1\", \"streamType\": \"1\"}", "{clientId}", sim); msg = StringUtils.replace(msg, "{tcpPort}", (port.intValue() + getIntPort() + getAddPort()) + ""); msg = StringUtils.replace(msg, "{udpPort}", (port.intValue() + getIntPort() + getAddPort()) + ""); msg = StringUtils.replace(msg, "{channelNo}", channel); return StringUtils.replace(msg, "{ip}", configBean.getRtspIp()); } public String formatMessageStop(String sim, String channel) { String msg = StringUtils.replace("{\"messageId\": 37122,\"properties\": 0,\"clientId\": \"{clientId}\",\"serialNo\": \"1\",\"channelNo\": \"{channelNo}\",\"command\": \"0\",\"closeType\": \"0\",\"streamType\": \"1\"}", "{clientId}", sim); return StringUtils.replace(msg, "{channelNo}", channel); } public String formatMessageHistoryListRTSP(String sim, String channel, String startTime, String endTime) { String msg = StringUtils.replace("{\"msgid\":37381,\"clientId\":\"{clientId}\",\"startTime\":\"{startTime}\",\"endTime\":\"{endTime}\",\"mediaType\":0,\"streamType\":1,\"storageType\":0,\"channelNo\":{channelNo}}", "{clientId}", sim); msg = StringUtils.replace(msg, "{startTime}", startTime); msg = StringUtils.replace(msg, "{endTime}", endTime); return StringUtils.replace(msg, "{channelNo}", channel); } public String formatMessageHistoryPlayRTSP(String sim, String channel, String startTime, String endTime, RtspConfigBean configBean, Integer port) { String msg = StringUtils.replace("{\"ip\":\"{ip}\",\"tcpPort\":{tcpPort},\"udpPort\":{udpPort},\"channelNo\":\"{channelNo}\",\"mediaType\":0,\"streamType\":0,\"storageType\":0,\"playbackType\":0,\"playbackSpeed\":1,\"startTime\":\"{startTime}\",\"endTime\":\"{endTime}\",\"clientId\":\"{sim}\",\"messageId\":37377}", "{clientId}", sim); msg = StringUtils.replace(msg, "{startTime}", startTime); msg = StringUtils.replace(msg, "{endTime}", endTime); msg = StringUtils.replace(msg, "{channelNo}", channel); msg = StringUtils.replace(msg, "{tcpPort}", (port.intValue() + getIntPort() +getAddPort()) + ""); msg = StringUtils.replace(msg, "{udpPort}", (port.intValue() + getIntPort() + getAddPort()) + ""); msg = StringUtils.replace(msg, "{sim}", sim); return StringUtils.replace(msg, "{ip}", configBean.getRtspIp()); } public String formatMessageHistoryStopRTSP(String sim, String channel, RtspConfigBean configBean) { String msg = StringUtils.replace("{\"playbackMode\":2,\"channelNo\":{channelNo},\"playbackSpeed\":0,\"clientId\":\"{sim}\"}", "{sim}", sim); return StringUtils.replace(msg, "{channelNo}", channel); } public String formatPushURL(String pushKey, int port, int httpPort) { String msg = StringUtils.replace(this.pushURL, "{pushKey}", pushKey); msg = StringUtils.replace(msg, "{port}", String.valueOf(port)); return StringUtils.replace(msg, "{httpPort}", String.valueOf(httpPort)); } public String formatStopPushURL(String pushKey, int port, int httpPort) { String msg = StringUtils.replace(this.stopPUshURL, "{pushKey}", pushKey); msg = StringUtils.replace(msg, "{port}", String.valueOf(port)); return StringUtils.replace(msg, "{httpPort}", String.valueOf(httpPort)); } public String formatVideoURL(String stream) { String url = StringUtils.replace(getGetURL(), "{stream}", stream); if (!StringUtils.endsWith(url, ".flv")) { url = url + ".flv"; } return url; } public String getJt1078Url() { return this.jt1078Url; } public String getJt1078SendPort() { return this.jt1078SendPort; } public String getStopSendPort() { return this.stopSendPort; } public String getHistoryListPort() { return this.historyListPort; } public String getPlayHistoryPort() { return this.playHistoryPort; } public String getPushURL() { return this.pushURL; } public Integer getStart1078Port() { if (Objects.isNull(this.start1078Port)) this.start1078Port = Integer.valueOf(Integer.parseInt(StringUtils.substringBefore(this.portsOf1078, ","))); return this.start1078Port; } public Integer getEnd1078Port() { if (Objects.isNull(this.end1078Port)) this.end1078Port = Integer.valueOf(Integer.parseInt(StringUtils.substringAfter(this.portsOf1078, ","))); return this.end1078Port; } public String getPushKey(){ if (Objects.isNull(this.pushKey)){ this.pushKey = "?callId=41db35390ddad33f83944f44b8b75ded"; } return "?callId="+this.pushKey; } public String getStopPUshURL() { return this.stopPUshURL; } public String getGetURL() { return this.getURL; } public Integer getAddPort() { return this.addPort; } public String getWs() { return this.ws; } public String getWss() { return this.wss; } public String getDownloadFlv() { return downloadFlv; } public String getPortsOf1078() { return portsOf1078; } } | ||
| 3 | \ No newline at end of file | 3 | \ No newline at end of file |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/config/TuohuaConfigBean.java
| 1 | package com.genersoft.iot.vmp.vmanager.jt1078.platform.config; | 1 | package com.genersoft.iot.vmp.vmanager.jt1078.platform.config; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.convert.Convert; | ||
| 3 | import com.alibaba.fastjson2.JSON; | 4 | import com.alibaba.fastjson2.JSON; |
| 4 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.ben.HttpClientPostEntity; | 5 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.ben.HttpClientPostEntity; |
| 6 | +import com.genersoft.iot.vmp.vmanager.jt1078.platform.domain.CarData; | ||
| 5 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.handler.HttpClientUtil; | 7 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.handler.HttpClientUtil; |
| 6 | -import com.xiaoleilu.hutool.convert.Convert; | 8 | +import lombok.extern.slf4j.Slf4j; |
| 7 | import org.apache.commons.collections4.CollectionUtils; | 9 | import org.apache.commons.collections4.CollectionUtils; |
| 8 | -import org.apache.commons.lang3.RandomUtils; | ||
| 9 | import org.apache.commons.lang3.StringUtils; | 10 | import org.apache.commons.lang3.StringUtils; |
| 10 | import org.springframework.beans.factory.annotation.Autowired; | 11 | import org.springframework.beans.factory.annotation.Autowired; |
| 11 | import org.springframework.beans.factory.annotation.Value; | 12 | import org.springframework.beans.factory.annotation.Value; |
| 12 | import org.springframework.data.redis.core.RedisTemplate; | 13 | import org.springframework.data.redis.core.RedisTemplate; |
| 13 | import org.springframework.stereotype.Component; | 14 | import org.springframework.stereotype.Component; |
| 14 | 15 | ||
| 16 | +import javax.annotation.PostConstruct; | ||
| 17 | +import javax.annotation.Resource; | ||
| 15 | import java.security.MessageDigest; | 18 | import java.security.MessageDigest; |
| 16 | import java.util.*; | 19 | import java.util.*; |
| 20 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 17 | import java.util.stream.Collectors; | 21 | import java.util.stream.Collectors; |
| 18 | 22 | ||
| 19 | /** | 23 | /** |
| 20 | * @author liujun | 24 | * @author liujun |
| 21 | * @date 2024年10月23日 13:34 | 25 | * @date 2024年10月23日 13:34 |
| 22 | */ | 26 | */ |
| 27 | +@Slf4j | ||
| 23 | @Component | 28 | @Component |
| 24 | public class TuohuaConfigBean { | 29 | public class TuohuaConfigBean { |
| 25 | 30 | ||
| @@ -50,6 +55,8 @@ public class TuohuaConfigBean { | @@ -50,6 +55,8 @@ public class TuohuaConfigBean { | ||
| 50 | @Value("${spring.profiles.active}") | 55 | @Value("${spring.profiles.active}") |
| 51 | private String profileActive; | 56 | private String profileActive; |
| 52 | 57 | ||
| 58 | + public static final ConcurrentHashMap<String, CarData> map = new ConcurrentHashMap<>(); | ||
| 59 | + | ||
| 53 | @Autowired | 60 | @Autowired |
| 54 | private RedisTemplate redisTemplate; | 61 | private RedisTemplate redisTemplate; |
| 55 | 62 | ||
| @@ -111,6 +118,19 @@ public class TuohuaConfigBean { | @@ -111,6 +118,19 @@ public class TuohuaConfigBean { | ||
| 111 | return Objects.isNull(postEntity) ? null : postEntity.getResultStr(); | 118 | return Objects.isNull(postEntity) ? null : postEntity.getResultStr(); |
| 112 | } | 119 | } |
| 113 | 120 | ||
| 121 | + @Resource | ||
| 122 | + private HttpClientUtil httpClientUtil; | ||
| 123 | + | ||
| 124 | + @PostConstruct | ||
| 125 | + public void init() { | ||
| 126 | + try { | ||
| 127 | + String carJson = requestCars(httpClientUtil, String.valueOf(100)); | ||
| 128 | + setMap(carJson); | ||
| 129 | + } catch (Exception e) { | ||
| 130 | + throw new RuntimeException(e); | ||
| 131 | + } | ||
| 132 | + } | ||
| 133 | + | ||
| 114 | public String requestCars(HttpClientUtil httpClientUtil, String companyId) throws Exception { | 134 | public String requestCars(HttpClientUtil httpClientUtil, String companyId) throws Exception { |
| 115 | String nonce = random(6); | 135 | String nonce = random(6); |
| 116 | String timestamp = String.valueOf(new Date().getTime()); | 136 | String timestamp = String.valueOf(new Date().getTime()); |
| @@ -140,6 +160,30 @@ public class TuohuaConfigBean { | @@ -140,6 +160,30 @@ public class TuohuaConfigBean { | ||
| 140 | return (List<HashMap>) JSON.parseArray(postEntity.getResultStr(), HashMap.class); | 160 | return (List<HashMap>) JSON.parseArray(postEntity.getResultStr(), HashMap.class); |
| 141 | } | 161 | } |
| 142 | 162 | ||
| 163 | + public void setMap(String json){ | ||
| 164 | + List<CarData> carData = JSON.parseArray(json, CarData.class); | ||
| 165 | + int count = 1; | ||
| 166 | + if (CollectionUtils.isNotEmpty(carData)) { | ||
| 167 | + if (StringUtils.equals(profileActive, "wx-local")) { | ||
| 168 | + CarData value = carData.get(0); | ||
| 169 | + value.setSim("123456789011"); | ||
| 170 | + map.put(value.getSim(), value); | ||
| 171 | + }else { | ||
| 172 | + for (CarData carDatum : carData) { | ||
| 173 | + log.debug("{} ----》 {}",count++,JSON.toJSONString(carDatum)); | ||
| 174 | + if (carDatum == null || carDatum.getSim() == null) { | ||
| 175 | + continue; | ||
| 176 | + } | ||
| 177 | + map.put(carDatum.getSim(), carDatum); | ||
| 178 | + } | ||
| 179 | + } | ||
| 180 | + } | ||
| 181 | + } | ||
| 182 | + | ||
| 183 | + public static CarData getCarData(String sim){ | ||
| 184 | + return map.get(sim); | ||
| 185 | + } | ||
| 186 | + | ||
| 143 | public List<HashMap<String, Object>> requestOfLineAndCarAndCombationTree(HttpClientUtil httpClientUtil, String companyId) throws Exception { | 187 | public List<HashMap<String, Object>> requestOfLineAndCarAndCombationTree(HttpClientUtil httpClientUtil, String companyId) throws Exception { |
| 144 | String lineJson = requestLine(httpClientUtil, companyId); | 188 | String lineJson = requestLine(httpClientUtil, companyId); |
| 145 | String carJson = requestCars(httpClientUtil, companyId); | 189 | String carJson = requestCars(httpClientUtil, companyId); |
| @@ -163,7 +207,10 @@ public class TuohuaConfigBean { | @@ -163,7 +207,10 @@ public class TuohuaConfigBean { | ||
| 163 | List<HashMap> carJsonListFinal = carJsonList; | 207 | List<HashMap> carJsonListFinal = carJsonList; |
| 164 | 208 | ||
| 165 | List<HashMap<String, Object>> returnData = new ArrayList<>(); | 209 | List<HashMap<String, Object>> returnData = new ArrayList<>(); |
| 210 | + | ||
| 211 | + | ||
| 166 | if (linesSize > 0) { | 212 | if (linesSize > 0) { |
| 213 | + setMap(carJson); | ||
| 167 | List<HashMap<String, Object>> lines = linesJsonList.stream().map(hashMap -> { | 214 | List<HashMap<String, Object>> lines = linesJsonList.stream().map(hashMap -> { |
| 168 | String code = convertStr(hashMap.get("lineCode")); | 215 | String code = convertStr(hashMap.get("lineCode")); |
| 169 | String name = convertStr(hashMap.get("name")); | 216 | String name = convertStr(hashMap.get("name")); |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/controller/FTPController.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.vmanager.jt1078.platform.controller; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.vmanager.jt1078.platform.service.FTPService; | ||
| 4 | +import org.springframework.web.bind.annotation.*; | ||
| 5 | + | ||
| 6 | +import javax.annotation.Resource; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * FTP控制层 | ||
| 10 | + * | ||
| 11 | + * @Author WangXin | ||
| 12 | + * @Data 2025/2/11 | ||
| 13 | + * @Version 1.0.0 | ||
| 14 | + */ | ||
| 15 | +@RestController | ||
| 16 | +@RequestMapping("/ftp") | ||
| 17 | +public class FTPController { | ||
| 18 | + | ||
| 19 | + @Resource | ||
| 20 | + private FTPService ftpService; | ||
| 21 | + | ||
| 22 | + /** | ||
| 23 | + * 文件上传 | ||
| 24 | + * @param sim sim号 | ||
| 25 | + * @param channel 通道号 | ||
| 26 | + * @param startTime 起始时间 | ||
| 27 | + * @param endTime 终止时间 | ||
| 28 | + * @return 上传结果 | ||
| 29 | + */ | ||
| 30 | + @GetMapping("/uploadFile/{sim}/{channel}/{startTime}/{endTime}") | ||
| 31 | + public String uploadFile(@PathVariable String sim, | ||
| 32 | + @PathVariable Integer channel, | ||
| 33 | + @PathVariable String startTime, | ||
| 34 | + @PathVariable String endTime) { | ||
| 35 | + return ftpService.uploadFile(sim, channel, startTime, endTime); | ||
| 36 | + } | ||
| 37 | +} |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/controller/FlowController.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.vmanager.jt1078.platform.controller; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.conf.exception.ServiceException; | ||
| 4 | +import com.genersoft.iot.vmp.vmanager.jt1078.platform.domain.SimFlow; | ||
| 5 | +import com.genersoft.iot.vmp.vmanager.jt1078.platform.service.FlowService; | ||
| 6 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 7 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 8 | +import org.springframework.web.bind.annotation.PathVariable; | ||
| 9 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 10 | +import org.springframework.web.bind.annotation.RestController; | ||
| 11 | + | ||
| 12 | +import javax.annotation.Resource; | ||
| 13 | +import java.util.Date; | ||
| 14 | +import java.util.List; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * 流量统计控制层 | ||
| 18 | + * | ||
| 19 | + * @Author WangXin | ||
| 20 | + * @Data 2025/2/10 | ||
| 21 | + * @Version 1.0.0 | ||
| 22 | + */ | ||
| 23 | +@RestController | ||
| 24 | +@RequestMapping("/flow") | ||
| 25 | +public class FlowController { | ||
| 26 | + | ||
| 27 | + @Resource | ||
| 28 | + private FlowService flowService; | ||
| 29 | + | ||
| 30 | + @GetMapping("/list/{timeType}/{statisticsType}/{time}/{sim}") | ||
| 31 | + public List<SimFlow> list(@PathVariable String statisticsType, | ||
| 32 | + @PathVariable String time, | ||
| 33 | + @PathVariable String timeType, | ||
| 34 | + @PathVariable String sim) throws ServiceException { | ||
| 35 | + return flowService.getList(timeType, statisticsType, time, sim); | ||
| 36 | + } | ||
| 37 | +} |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/domain/ApiResult.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.vmanager.jt1078.platform.domain; | ||
| 2 | + | ||
| 3 | +import lombok.AllArgsConstructor; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import lombok.NoArgsConstructor; | ||
| 6 | +import lombok.experimental.SuperBuilder; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 大邑APi返回结果集 | ||
| 10 | + * | ||
| 11 | + * @Author WangXin | ||
| 12 | + * @Data 2025/2/11 | ||
| 13 | + * @Version 1.0.0 | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | +@Data | ||
| 17 | +@SuperBuilder | ||
| 18 | +@AllArgsConstructor | ||
| 19 | +@NoArgsConstructor | ||
| 20 | +public class ApiResult { | ||
| 21 | + /** | ||
| 22 | + * 响应码(成功:200;客户端错误:400-499;服务端错误:500-599) | ||
| 23 | + */ | ||
| 24 | + private Integer code; | ||
| 25 | + /** | ||
| 26 | + * 响应消息 | ||
| 27 | + */ | ||
| 28 | + private String msg; | ||
| 29 | + /** | ||
| 30 | + * 响应消息详情 | ||
| 31 | + */ | ||
| 32 | + private String detailMsg; | ||
| 33 | + /** | ||
| 34 | + * 响应消息体 | ||
| 35 | + */ | ||
| 36 | + private ApiResultData data; | ||
| 37 | +} |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/domain/ApiResultData.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.vmanager.jt1078.platform.domain; | ||
| 2 | + | ||
| 3 | +import lombok.AllArgsConstructor; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import lombok.NoArgsConstructor; | ||
| 6 | +import lombok.experimental.SuperBuilder; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 大邑Api响应消息体 | ||
| 10 | + * @Author WangXin | ||
| 11 | + * @Data 2025/2/11 | ||
| 12 | + * @Version 1.0.0 | ||
| 13 | + */ | ||
| 14 | + | ||
| 15 | +@Data | ||
| 16 | +@SuperBuilder | ||
| 17 | +@AllArgsConstructor | ||
| 18 | +@NoArgsConstructor | ||
| 19 | +public class ApiResultData { | ||
| 20 | + /** | ||
| 21 | + * 终端手机号 | ||
| 22 | + */ | ||
| 23 | + private String clientId; | ||
| 24 | + /** | ||
| 25 | + * 应答流水号 | ||
| 26 | + */ | ||
| 27 | + private Integer responseSerialNo; | ||
| 28 | + /** | ||
| 29 | + * 应答Id | ||
| 30 | + */ | ||
| 31 | + private Integer responseMessageId; | ||
| 32 | + /** | ||
| 33 | + * 结果:0.成功 1.失败 2.消息有误 3.不支持 4.报警处理确认 | ||
| 34 | + */ | ||
| 35 | + private Integer resultCode; | ||
| 36 | +} |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/domain/SimFlow.java
| 1 | package com.genersoft.iot.vmp.vmanager.jt1078.platform.domain; | 1 | package com.genersoft.iot.vmp.vmanager.jt1078.platform.domain; |
| 2 | 2 | ||
| 3 | import com.fasterxml.jackson.annotation.JsonFormat; | 3 | import com.fasterxml.jackson.annotation.JsonFormat; |
| 4 | +import lombok.AllArgsConstructor; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import lombok.NoArgsConstructor; | ||
| 7 | +import lombok.experimental.SuperBuilder; | ||
| 4 | import org.springframework.format.annotation.DateTimeFormat; | 8 | import org.springframework.format.annotation.DateTimeFormat; |
| 5 | 9 | ||
| 6 | import java.text.SimpleDateFormat; | 10 | import java.text.SimpleDateFormat; |
| @@ -13,53 +17,19 @@ import java.util.Date; | @@ -13,53 +17,19 @@ import java.util.Date; | ||
| 13 | * @Data 2025/1/7 | 17 | * @Data 2025/1/7 |
| 14 | * @Version 1.0.0 | 18 | * @Version 1.0.0 |
| 15 | */ | 19 | */ |
| 20 | +@Data | ||
| 21 | +@SuperBuilder | ||
| 22 | +@AllArgsConstructor | ||
| 23 | +@NoArgsConstructor | ||
| 16 | public class SimFlow { | 24 | public class SimFlow { |
| 17 | 25 | ||
| 18 | private String id; | 26 | private String id; |
| 19 | private String sim; | 27 | private String sim; |
| 20 | - private String channel; | ||
| 21 | - private Double flow; | 28 | + private Integer channel; |
| 29 | + private Long flow; | ||
| 30 | + private Integer count; | ||
| 22 | private String time; | 31 | private String time; |
| 23 | - | ||
| 24 | - public String getId() { | ||
| 25 | - return id; | ||
| 26 | - } | ||
| 27 | - | ||
| 28 | - public void setId(String id) { | ||
| 29 | - this.id = id; | ||
| 30 | - } | ||
| 31 | - | ||
| 32 | - public String getSim() { | ||
| 33 | - return sim; | ||
| 34 | - } | ||
| 35 | - | ||
| 36 | - public void setSim(String sim) { | ||
| 37 | - this.sim = sim; | ||
| 38 | - } | ||
| 39 | - | ||
| 40 | - public String getChannel() { | ||
| 41 | - return channel; | ||
| 42 | - } | ||
| 43 | - | ||
| 44 | - public void setChannel(String channel) { | ||
| 45 | - this.channel = channel; | ||
| 46 | - } | ||
| 47 | - | ||
| 48 | - public Double getFlow() { | ||
| 49 | - return flow; | ||
| 50 | - } | ||
| 51 | - | ||
| 52 | - public void setFlow(Double flow) { | ||
| 53 | - this.flow = flow; | ||
| 54 | - } | ||
| 55 | - | ||
| 56 | - public String getTime() { | ||
| 57 | - return time; | ||
| 58 | - } | ||
| 59 | - | ||
| 60 | - public void setTime(String time) { | ||
| 61 | - this.time = time; | ||
| 62 | - } | 32 | + private CarData carData; |
| 63 | 33 | ||
| 64 | @Override | 34 | @Override |
| 65 | public String toString() { | 35 | public String toString() { |
| @@ -72,13 +42,4 @@ public class SimFlow { | @@ -72,13 +42,4 @@ public class SimFlow { | ||
| 72 | sb.append('}'); | 42 | sb.append('}'); |
| 73 | return sb.toString(); | 43 | return sb.toString(); |
| 74 | } | 44 | } |
| 75 | - | ||
| 76 | - public static SimFlow build(String sim, String channel, Double flow) { | ||
| 77 | - SimFlow simFlow = new SimFlow(); | ||
| 78 | - simFlow.setSim(sim); | ||
| 79 | - simFlow.setChannel(channel); | ||
| 80 | - simFlow.setFlow(flow); | ||
| 81 | - simFlow.setTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date())); | ||
| 82 | - return simFlow; | ||
| 83 | - } | ||
| 84 | } | 45 | } |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/domain/UploadFileReq.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.vmanager.jt1078.platform.domain; | ||
| 2 | + | ||
| 3 | +import lombok.AllArgsConstructor; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import lombok.NoArgsConstructor; | ||
| 6 | +import lombok.experimental.SuperBuilder; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 文件上传请求对象 | ||
| 10 | + * | ||
| 11 | + * @Author WangXin | ||
| 12 | + * @Data 2025/2/11 | ||
| 13 | + * @Version 1.0.0 | ||
| 14 | + */ | ||
| 15 | +@Data | ||
| 16 | +@SuperBuilder | ||
| 17 | +@AllArgsConstructor | ||
| 18 | +@NoArgsConstructor | ||
| 19 | +public class UploadFileReq { | ||
| 20 | + | ||
| 21 | + /** | ||
| 22 | + * 终端手机号 | ||
| 23 | + */ | ||
| 24 | + private String clientId; | ||
| 25 | + /** | ||
| 26 | + * FTP服务器地址 | ||
| 27 | + */ | ||
| 28 | + private String ip; | ||
| 29 | + /** | ||
| 30 | + * FTP服务器端口 | ||
| 31 | + */ | ||
| 32 | + private Integer port; | ||
| 33 | + /** | ||
| 34 | + * FTP服务器用户名 | ||
| 35 | + */ | ||
| 36 | + private String username; | ||
| 37 | + /** | ||
| 38 | + * FTP服务器密码 | ||
| 39 | + */ | ||
| 40 | + private String password; | ||
| 41 | + /** | ||
| 42 | + * 文件上传路径 | ||
| 43 | + */ | ||
| 44 | + private String path; | ||
| 45 | + /** | ||
| 46 | + * 逻辑通道号 | ||
| 47 | + */ | ||
| 48 | + private Integer channelNo; | ||
| 49 | + /** | ||
| 50 | + * 开始时间 | ||
| 51 | + */ | ||
| 52 | + private String startTime; | ||
| 53 | + /** | ||
| 54 | + * 结束时间 | ||
| 55 | + */ | ||
| 56 | + private String endTime; | ||
| 57 | + /** | ||
| 58 | + * 报警标志0~31(参考808协议文档报警标志位定义) | ||
| 59 | + */ | ||
| 60 | + private Integer warnBit1 = 0; | ||
| 61 | + /** | ||
| 62 | + * 报警标志32~63 | ||
| 63 | + */ | ||
| 64 | + private Integer warnBit2 = 0; | ||
| 65 | + /** | ||
| 66 | + * 音视频资源类型:0.音视频 1.音频 2.视频 3.视频或音视频 | ||
| 67 | + */ | ||
| 68 | + private Integer mediaType = 0; | ||
| 69 | + /** | ||
| 70 | + * 码流类型:0.所有码流 1.主码流 2.子码流 | ||
| 71 | + */ | ||
| 72 | + private Integer streamType = 1; | ||
| 73 | + /** | ||
| 74 | + * 存储位置:0.所有存储器 1.主存储器 2.灾备存储器 | ||
| 75 | + */ | ||
| 76 | + private Integer storageType = 0; | ||
| 77 | + /** | ||
| 78 | + * 任务执行条件(用bit位表示):[0]WIFI下可下载 [1]LAN连接时可下载 [2]3G/4G连接时可下载 | ||
| 79 | + */ | ||
| 80 | + private Integer condition = 0; | ||
| 81 | +} |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/handler/HttpClientUtil.java
| @@ -38,6 +38,7 @@ public class HttpClientUtil { | @@ -38,6 +38,7 @@ public class HttpClientUtil { | ||
| 38 | private static final Logger log = LoggerFactory.getLogger(HttpClientUtil.class); | 38 | private static final Logger log = LoggerFactory.getLogger(HttpClientUtil.class); |
| 39 | 39 | ||
| 40 | public HttpClientPostEntity doPost(String url, Map<String, String> params, String jsessionid) throws URISyntaxException, IOException { | 40 | public HttpClientPostEntity doPost(String url, Map<String, String> params, String jsessionid) throws URISyntaxException, IOException { |
| 41 | + long startTime = System.currentTimeMillis(); | ||
| 41 | // 创建Httpclient对象 | 42 | // 创建Httpclient对象 |
| 42 | DefaultHttpClient httpclient = getHttpClient(); | 43 | DefaultHttpClient httpclient = getHttpClient(); |
| 43 | // 定义请求的参数 | 44 | // 定义请求的参数 |
| @@ -64,7 +65,7 @@ public class HttpClientUtil { | @@ -64,7 +65,7 @@ public class HttpClientUtil { | ||
| 64 | response = httpclient.execute(httpPost); | 65 | response = httpclient.execute(httpPost); |
| 65 | // 判断返回状态是否为200 | 66 | // 判断返回状态是否为200 |
| 66 | if (response.getStatusLine().getStatusCode() == 200) { | 67 | if (response.getStatusLine().getStatusCode() == 200) { |
| 67 | - return combationReturnObj(response, httpclient,url, null); | 68 | + return combationReturnObj(response, httpclient,url, null,startTime); |
| 68 | } | 69 | } |
| 69 | } finally { | 70 | } finally { |
| 70 | if (response != null) { | 71 | if (response != null) { |
| @@ -76,6 +77,7 @@ public class HttpClientUtil { | @@ -76,6 +77,7 @@ public class HttpClientUtil { | ||
| 76 | } | 77 | } |
| 77 | 78 | ||
| 78 | public HttpClientPostEntity doPost(String url, String requestBody, String jsessionid) throws URISyntaxException, IOException { | 79 | public HttpClientPostEntity doPost(String url, String requestBody, String jsessionid) throws URISyntaxException, IOException { |
| 80 | + long startTime = System.currentTimeMillis(); | ||
| 79 | // 创建Httpclient对象 | 81 | // 创建Httpclient对象 |
| 80 | DefaultHttpClient httpclient = getHttpClient(); | 82 | DefaultHttpClient httpclient = getHttpClient(); |
| 81 | // 定义请求的参数 | 83 | // 定义请求的参数 |
| @@ -99,7 +101,7 @@ public class HttpClientUtil { | @@ -99,7 +101,7 @@ public class HttpClientUtil { | ||
| 99 | response = httpclient.execute(httpPost); | 101 | response = httpclient.execute(httpPost); |
| 100 | // 判断返回状态是否为200 | 102 | // 判断返回状态是否为200 |
| 101 | if (response.getStatusLine().getStatusCode() == 200) { | 103 | if (response.getStatusLine().getStatusCode() == 200) { |
| 102 | - return combationReturnObj(response, httpclient,url,requestBody); | 104 | + return combationReturnObj(response, httpclient,url,requestBody,startTime); |
| 103 | } | 105 | } |
| 104 | } catch (Exception e) { | 106 | } catch (Exception e) { |
| 105 | log.error("请求数据异常", e); | 107 | log.error("请求数据异常", e); |
| @@ -130,6 +132,7 @@ public class HttpClientUtil { | @@ -130,6 +132,7 @@ public class HttpClientUtil { | ||
| 130 | } | 132 | } |
| 131 | 133 | ||
| 132 | public HttpClientPostEntity doGet(String url, String jsessionid) throws URISyntaxException, IOException { | 134 | public HttpClientPostEntity doGet(String url, String jsessionid) throws URISyntaxException, IOException { |
| 135 | + long startTime = System.currentTimeMillis(); | ||
| 133 | // 创建Httpclient对象 | 136 | // 创建Httpclient对象 |
| 134 | DefaultHttpClient httpclient = getHttpClient(); | 137 | DefaultHttpClient httpclient = getHttpClient(); |
| 135 | // 定义请求的参数 | 138 | // 定义请求的参数 |
| @@ -151,7 +154,7 @@ public class HttpClientUtil { | @@ -151,7 +154,7 @@ public class HttpClientUtil { | ||
| 151 | response = httpclient.execute(httpGet); | 154 | response = httpclient.execute(httpGet); |
| 152 | // 判断返回状态是否为200 | 155 | // 判断返回状态是否为200 |
| 153 | if (response.getStatusLine().getStatusCode() == 200) { | 156 | if (response.getStatusLine().getStatusCode() == 200) { |
| 154 | - return combationReturnObj(response, httpclient,url,null); | 157 | + return combationReturnObj(response, httpclient,url,null,startTime); |
| 155 | } | 158 | } |
| 156 | } finally { | 159 | } finally { |
| 157 | if (response != null) { | 160 | if (response != null) { |
| @@ -204,7 +207,7 @@ public class HttpClientUtil { | @@ -204,7 +207,7 @@ public class HttpClientUtil { | ||
| 204 | * @throws IOException | 207 | * @throws IOException |
| 205 | */ | 208 | */ |
| 206 | @NotNull | 209 | @NotNull |
| 207 | - private static HttpClientPostEntity combationReturnObj(CloseableHttpResponse response, DefaultHttpClient httpclient,String url,String requestBody) throws IOException { | 210 | + private static HttpClientPostEntity combationReturnObj(CloseableHttpResponse response, DefaultHttpClient httpclient,String url,String requestBody,long startTime) throws IOException { |
| 208 | HttpEntity httpEntity = response.getEntity(); | 211 | HttpEntity httpEntity = response.getEntity(); |
| 209 | 212 | ||
| 210 | CookieStore cookieStore = httpclient.getCookieStore(); | 213 | CookieStore cookieStore = httpclient.getCookieStore(); |
| @@ -213,7 +216,7 @@ public class HttpClientUtil { | @@ -213,7 +216,7 @@ public class HttpClientUtil { | ||
| 213 | HttpClientPostEntity postEntity = new HttpClientPostEntity(); | 216 | HttpClientPostEntity postEntity = new HttpClientPostEntity(); |
| 214 | postEntity.setCookieStore(cookieStore); | 217 | postEntity.setCookieStore(cookieStore); |
| 215 | postEntity.setResultStr(result); | 218 | postEntity.setResultStr(result); |
| 216 | - log.info("url:{};requestBody:{};response :{}",url,requestBody,"请求成功"); | 219 | + log.info("url:{};requestBody:{};response :{}; 耗时: {}s ",url,requestBody,"请求成功",System.currentTimeMillis()-startTime); |
| 217 | return postEntity; | 220 | return postEntity; |
| 218 | } | 221 | } |
| 219 | 222 |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/mapper/FlowMapper.java
| @@ -16,30 +16,39 @@ public interface FlowMapper { | @@ -16,30 +16,39 @@ public interface FlowMapper { | ||
| 16 | 16 | ||
| 17 | @Select(value = {" <script>" + | 17 | @Select(value = {" <script>" + |
| 18 | "SELECT " + | 18 | "SELECT " + |
| 19 | - " <if test=\"time != null and time == 'day'\" >" + | 19 | + " <if test=\"timeType != null and timeType == 'day'\" >" + |
| 20 | " `time`," + | 20 | " `time`," + |
| 21 | " </if>" + | 21 | " </if>" + |
| 22 | - " <if test=\"time != null and time == 'year'\" >" + | 22 | + " <if test=\"timeType != null and timeType == 'year'\" >" + |
| 23 | " YEAR(`time`) `time`," + | 23 | " YEAR(`time`) `time`," + |
| 24 | " </if>" + | 24 | " </if>" + |
| 25 | - " <if test=\"time != null and time == 'month'\" >" + | 25 | + " <if test=\"timeType != null and timeType == 'month'\" >" + |
| 26 | " CONCAT(YEAR(`time`),'-',MONTH(`time`)) `time`," + | 26 | " CONCAT(YEAR(`time`),'-',MONTH(`time`)) `time`," + |
| 27 | " </if>" + | 27 | " </if>" + |
| 28 | - " `sim`, `channel`, SUM(flow) flow" + | 28 | + " `sim`, `channel`, SUM(flow) flow " + |
| 29 | + " <if test=\"statisticsType!=null and statisticsType !='' and statisticsType == 'All'\"> " + | ||
| 30 | + " ,COUNT(DISTINCT sim) count " + | ||
| 31 | + " </if>" + | ||
| 29 | " FROM `wvp_sim_flow`" + | 32 | " FROM `wvp_sim_flow`" + |
| 30 | " <where> " + | 33 | " <where> " + |
| 31 | - " <if test=\"time != null and time != '' and statisticsType = 'day'\">" + | 34 | + " <if test=\"time != null and time != 'null' and time != 'undefined' and time != '' and timeType == 'day'\">" + |
| 32 | " AND time = #{time}" + | 35 | " AND time = #{time}" + |
| 33 | " </if>" + | 36 | " </if>" + |
| 34 | - " <if test=\"time != null and time != '' and statisticsType = 'month'\">" + | 37 | + " <if test=\"time != null and time != 'null' and time != 'undefined' and time != '' and timeType == 'month'\">" + |
| 35 | " AND CONCAT(YEAR(`time`),'-',MONTH(`time`)) = #{time}" + | 38 | " AND CONCAT(YEAR(`time`),'-',MONTH(`time`)) = #{time}" + |
| 36 | " </if>" + | 39 | " </if>" + |
| 37 | - " <if test=\"time != null and time != '' and statisticsType = 'year'\">" + | 40 | + " <if test=\"time != null and time != 'null' and time != 'undefined' and time != '' and timeType == 'year'\">" + |
| 38 | " AND YEAR(`time`) = #{time}" + | 41 | " AND YEAR(`time`) = #{time}" + |
| 39 | " </if>" + | 42 | " </if>" + |
| 43 | + " <if test=\"sim != null and sim != '' and sim != 'null' and sim != 'undefined'\"> " + | ||
| 44 | + " AND sim like CONCAT('%',#{sim})" + | ||
| 45 | + " </if>" + | ||
| 40 | " </where>" + | 46 | " </where>" + |
| 41 | - " GROUP BY sim " + | ||
| 42 | - " <if test=\"statisticsType!=null and statisticsType !='' and statisticsType = 'channel' \">" + | 47 | + " <trim prefix=\"GROUP BY\" prefixOverrides=\",\">" + |
| 48 | + " <if test=\"statisticsType!=null and statisticsType !='' and statisticsType != 'All'\"> " + | ||
| 49 | + " ,sim " + | ||
| 50 | + " </if>" + | ||
| 51 | + " <if test=\"statisticsType!=null and statisticsType !='' and statisticsType == 'channel' \">" + | ||
| 43 | " ,`channel` " + | 52 | " ,`channel` " + |
| 44 | " </if>" + | 53 | " </if>" + |
| 45 | " <if test=\"timeType == 'day'\">" + | 54 | " <if test=\"timeType == 'day'\">" + |
| @@ -51,10 +60,11 @@ public interface FlowMapper { | @@ -51,10 +60,11 @@ public interface FlowMapper { | ||
| 51 | " <if test=\"timeType == 'month'\" >" + | 60 | " <if test=\"timeType == 'month'\" >" + |
| 52 | " ,CONCAT(YEAR(`time`),'-',MONTH(`time`))" + | 61 | " ,CONCAT(YEAR(`time`),'-',MONTH(`time`))" + |
| 53 | " </if>" + | 62 | " </if>" + |
| 63 | + "</trim>" + | ||
| 54 | " ORDER BY `time` DESC " + | 64 | " ORDER BY `time` DESC " + |
| 55 | " </script>"} | 65 | " </script>"} |
| 56 | ) | 66 | ) |
| 57 | - List<SimFlow> getList(@Param("timeType") String timeType, @Param("statisticsType") String statisticsType, @Param("time") String time); | 67 | + List<SimFlow> getList(@Param("timeType") String timeType, @Param("statisticsType") String statisticsType, @Param("time") String time, @Param("sim") String sim); |
| 58 | 68 | ||
| 59 | @Insert( | 69 | @Insert( |
| 60 | "INSERT INTO " + | 70 | "INSERT INTO " + |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/remote/DaYiApi.java
| 1 | package com.genersoft.iot.vmp.vmanager.jt1078.platform.remote; | 1 | package com.genersoft.iot.vmp.vmanager.jt1078.platform.remote; |
| 2 | 2 | ||
| 3 | import com.dtflys.forest.annotation.Address; | 3 | import com.dtflys.forest.annotation.Address; |
| 4 | +import com.dtflys.forest.annotation.JSONBody; | ||
| 5 | +import com.dtflys.forest.annotation.Post; | ||
| 6 | +import com.genersoft.iot.vmp.vmanager.jt1078.platform.domain.ApiResult; | ||
| 7 | +import com.genersoft.iot.vmp.vmanager.jt1078.platform.domain.UploadFileReq; | ||
| 4 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.remote.cnofig.DaYiAddressSourceConfig; | 8 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.remote.cnofig.DaYiAddressSourceConfig; |
| 5 | 9 | ||
| 6 | /** | 10 | /** |
| @@ -11,4 +15,13 @@ import com.genersoft.iot.vmp.vmanager.jt1078.platform.remote.cnofig.DaYiAddressS | @@ -11,4 +15,13 @@ import com.genersoft.iot.vmp.vmanager.jt1078.platform.remote.cnofig.DaYiAddressS | ||
| 11 | */ | 15 | */ |
| 12 | @Address(source = DaYiAddressSourceConfig.class) | 16 | @Address(source = DaYiAddressSourceConfig.class) |
| 13 | public interface DaYiApi { | 17 | public interface DaYiApi { |
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * 文件上传指令 | ||
| 21 | + * @param uploadFileReq 上传文件请求对象 | ||
| 22 | + * @return 结果集 | ||
| 23 | + */ | ||
| 24 | + @Post("/9206") | ||
| 25 | + ApiResult uploadFile(@JSONBody UploadFileReq uploadFileReq); | ||
| 26 | + | ||
| 14 | } | 27 | } |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/remote/cnofig/DaYiAddressSourceConfig.java
| @@ -17,10 +17,8 @@ import static com.genersoft.iot.vmp.vmanager.util.URLParser.parseURL; | @@ -17,10 +17,8 @@ import static com.genersoft.iot.vmp.vmanager.util.URLParser.parseURL; | ||
| 17 | @Configuration | 17 | @Configuration |
| 18 | public class DaYiAddressSourceConfig implements AddressSource { | 18 | public class DaYiAddressSourceConfig implements AddressSource { |
| 19 | 19 | ||
| 20 | - @Value("${tuohua.bsth.login.rest.baseURL}") | 20 | + @Value("${tuohua.bsth.jt1078.new_url}") |
| 21 | public String baseURL; | 21 | public String baseURL; |
| 22 | - @Value("${tuohua.bsth.login.rest.password}") | ||
| 23 | - private String restPassword; | ||
| 24 | 22 | ||
| 25 | @Override | 23 | @Override |
| 26 | public ForestAddress getAddress(ForestRequest request) { | 24 | public ForestAddress getAddress(ForestRequest request) { |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/service/FTPService.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.vmanager.jt1078.platform.service; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * @Author WangXin | ||
| 5 | + * @Data 2025/2/11 | ||
| 6 | + * @Version 1.0.0 | ||
| 7 | + */ | ||
| 8 | +public interface FTPService { | ||
| 9 | + /** | ||
| 10 | + * 文件上传 | ||
| 11 | + * @param sim sim号 | ||
| 12 | + * @param channel 通道号 | ||
| 13 | + * @param startTime 起始时间 | ||
| 14 | + * @param endTime 终止时间 | ||
| 15 | + * @return 上传结果 | ||
| 16 | + */ | ||
| 17 | + String uploadFile(String sim, Integer channel, String startTime, String endTime); | ||
| 18 | +} |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/service/FlowService.java
| 1 | package com.genersoft.iot.vmp.vmanager.jt1078.platform.service; | 1 | package com.genersoft.iot.vmp.vmanager.jt1078.platform.service; |
| 2 | 2 | ||
| 3 | +import com.genersoft.iot.vmp.conf.exception.ServiceException; | ||
| 3 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.domain.SimFlow; | 4 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.domain.SimFlow; |
| 4 | 5 | ||
| 6 | +import java.util.Date; | ||
| 5 | import java.util.List; | 7 | import java.util.List; |
| 6 | -import java.util.Map; | ||
| 7 | 8 | ||
| 8 | /** | 9 | /** |
| 9 | * @Author WangXin | 10 | * @Author WangXin |
| @@ -13,10 +14,12 @@ import java.util.Map; | @@ -13,10 +14,12 @@ import java.util.Map; | ||
| 13 | public interface FlowService { | 14 | public interface FlowService { |
| 14 | /** | 15 | /** |
| 15 | * 流量列表 | 16 | * 流量列表 |
| 16 | - * @param timeType 时间类型 | 17 | + * |
| 18 | + * @param timeType 时间类型 | ||
| 17 | * @param statisticsType 统计类型 | 19 | * @param statisticsType 统计类型 |
| 20 | + * @param sim | ||
| 18 | */ | 21 | */ |
| 19 | - Map<String, SimFlow> getList(String timeType, String statisticsType, String time); | 22 | + List<SimFlow> getList(String timeType, String statisticsType, String time, String sim) throws ServiceException; |
| 20 | 23 | ||
| 21 | /** | 24 | /** |
| 22 | * 批量添加流量记录 | 25 | * 批量添加流量记录 |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/service/impl/FTPServiceImpl.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.vmanager.jt1078.platform.service.impl; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.vmanager.jt1078.platform.config.FtpConfigBean; | ||
| 4 | +import com.genersoft.iot.vmp.vmanager.jt1078.platform.domain.ApiResult; | ||
| 5 | +import com.genersoft.iot.vmp.vmanager.jt1078.platform.domain.UploadFileReq; | ||
| 6 | +import com.genersoft.iot.vmp.vmanager.jt1078.platform.remote.DaYiApi; | ||
| 7 | +import com.genersoft.iot.vmp.vmanager.jt1078.platform.service.FTPService; | ||
| 8 | +import org.springframework.stereotype.Service; | ||
| 9 | + | ||
| 10 | +import javax.annotation.Resource; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * @Author WangXin | ||
| 14 | + * @Data 2025/2/11 | ||
| 15 | + * @Version 1.0.0 | ||
| 16 | + */ | ||
| 17 | +@Service | ||
| 18 | +public class FTPServiceImpl implements FTPService { | ||
| 19 | + | ||
| 20 | + @Resource | ||
| 21 | + private DaYiApi daYiApi; | ||
| 22 | + @Resource | ||
| 23 | + private FtpConfigBean ftpConfigBean; | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + @Override | ||
| 27 | + public String uploadFile(String sim, Integer channel, String startTime, String endTime) { | ||
| 28 | + | ||
| 29 | + ApiResult apiResult = daYiApi.uploadFile( | ||
| 30 | + UploadFileReq.builder() | ||
| 31 | + .ip(ftpConfigBean.getHost()) | ||
| 32 | + .port(ftpConfigBean.getPort()) | ||
| 33 | + .password(ftpConfigBean.getPassword()) | ||
| 34 | + .username(ftpConfigBean.getUsername()) | ||
| 35 | + .clientId(sim) | ||
| 36 | + .startTime(startTime) | ||
| 37 | + .endTime(endTime) | ||
| 38 | + .channelNo(channel) | ||
| 39 | + .build()); | ||
| 40 | + return apiResult.getMsg(); | ||
| 41 | + } | ||
| 42 | +} |
src/main/java/com/genersoft/iot/vmp/vmanager/jt1078/platform/service/impl/FlowServiceImpl.java
| 1 | package com.genersoft.iot.vmp.vmanager.jt1078.platform.service.impl; | 1 | package com.genersoft.iot.vmp.vmanager.jt1078.platform.service.impl; |
| 2 | 2 | ||
| 3 | +import com.genersoft.iot.vmp.conf.exception.ServiceException; | ||
| 3 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.domain.SimFlow; | 4 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.domain.SimFlow; |
| 4 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.mapper.FlowMapper; | 5 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.mapper.FlowMapper; |
| 5 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.service.FlowService; | 6 | import com.genersoft.iot.vmp.vmanager.jt1078.platform.service.FlowService; |
| 6 | import org.springframework.stereotype.Service; | 7 | import org.springframework.stereotype.Service; |
| 7 | 8 | ||
| 8 | import javax.annotation.Resource; | 9 | import javax.annotation.Resource; |
| 9 | -import java.util.*; | 10 | +import java.util.List; |
| 11 | +import java.util.UUID; | ||
| 10 | import java.util.stream.Collectors; | 12 | import java.util.stream.Collectors; |
| 11 | 13 | ||
| 14 | +import static com.genersoft.iot.vmp.vmanager.jt1078.platform.config.TuohuaConfigBean.getCarData; | ||
| 15 | + | ||
| 12 | /** | 16 | /** |
| 13 | * @Author WangXin | 17 | * @Author WangXin |
| 14 | * @Data 2025/1/7 | 18 | * @Data 2025/1/7 |
| @@ -21,11 +25,12 @@ public class FlowServiceImpl implements FlowService { | @@ -21,11 +25,12 @@ public class FlowServiceImpl implements FlowService { | ||
| 21 | private FlowMapper flowMapper; | 25 | private FlowMapper flowMapper; |
| 22 | 26 | ||
| 23 | @Override | 27 | @Override |
| 24 | - public Map<String, SimFlow> getList(String timeType, String statisticsType, String time) { | ||
| 25 | - List<SimFlow> list = flowMapper.getList(timeType, statisticsType, time); | ||
| 26 | - | ||
| 27 | - | ||
| 28 | - return null; | 28 | + public List<SimFlow> getList(String timeType, String statisticsType, String time, String sim) throws ServiceException { |
| 29 | + if (timeType != null && "day".equals(timeType) && time != null && !"null".equals(time)) { | ||
| 30 | + time = time.split(" ")[0]; | ||
| 31 | + } | ||
| 32 | + return flowMapper.getList(timeType, statisticsType, time, sim) | ||
| 33 | + .stream().peek(simFlow -> simFlow.setCarData(getCarData(simFlow.getSim()))).collect(Collectors.toList()); | ||
| 29 | } | 34 | } |
| 30 | 35 | ||
| 31 | @Override | 36 | @Override |
src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java
| 1 | package com.genersoft.iot.vmp.vmanager.streamProxy; | 1 | package com.genersoft.iot.vmp.vmanager.streamProxy; |
| 2 | 2 | ||
| 3 | import com.alibaba.fastjson2.JSONObject; | 3 | import com.alibaba.fastjson2.JSONObject; |
| 4 | -import com.genersoft.iot.vmp.common.GeneralCallback; | ||
| 5 | import com.genersoft.iot.vmp.common.StreamInfo; | 4 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 6 | import com.genersoft.iot.vmp.conf.UserSetting; | 5 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 7 | import com.genersoft.iot.vmp.conf.exception.ControllerException; | 6 | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java
| @@ -30,13 +30,11 @@ import org.springframework.http.HttpStatus; | @@ -30,13 +30,11 @@ import org.springframework.http.HttpStatus; | ||
| 30 | import org.springframework.http.ResponseEntity; | 30 | import org.springframework.http.ResponseEntity; |
| 31 | import org.springframework.stereotype.Controller; | 31 | import org.springframework.stereotype.Controller; |
| 32 | import org.springframework.util.ObjectUtils; | 32 | import org.springframework.util.ObjectUtils; |
| 33 | -import org.springframework.util.StringUtils; | ||
| 34 | import org.springframework.web.bind.annotation.*; | 33 | import org.springframework.web.bind.annotation.*; |
| 35 | import org.springframework.web.context.request.async.DeferredResult; | 34 | import org.springframework.web.context.request.async.DeferredResult; |
| 36 | import org.springframework.web.multipart.MultipartFile; | 35 | import org.springframework.web.multipart.MultipartFile; |
| 37 | 36 | ||
| 38 | import javax.annotation.Resource; | 37 | import javax.annotation.Resource; |
| 39 | -import javax.servlet.ServletException; | ||
| 40 | import javax.servlet.http.HttpServletRequest; | 38 | import javax.servlet.http.HttpServletRequest; |
| 41 | import java.io.IOException; | 39 | import java.io.IOException; |
| 42 | import java.io.InputStream; | 40 | import java.io.InputStream; |
src/main/java/com/genersoft/iot/vmp/vmanager/util/FTPUtils.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.vmanager.util; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.vmanager.jt1078.platform.config.FtpConfigBean; | ||
| 4 | +import lombok.extern.log4j.Log4j2; | ||
| 5 | +import org.apache.commons.net.ftp.FTPClient; | ||
| 6 | +import org.apache.commons.net.ftp.FTPReply; | ||
| 7 | +import org.springframework.stereotype.Component; | ||
| 8 | + | ||
| 9 | +import javax.annotation.Resource; | ||
| 10 | +import java.io.IOException; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * FTP工具类 | ||
| 14 | + * | ||
| 15 | + * @Author WangXin | ||
| 16 | + * @Data 2025/2/11 | ||
| 17 | + * @Version 1.0.0 | ||
| 18 | + */ | ||
| 19 | +@Log4j2 | ||
| 20 | +@Component | ||
| 21 | +public class FTPUtils { | ||
| 22 | + | ||
| 23 | + @Resource | ||
| 24 | + private FtpConfigBean ftpConfigBean; | ||
| 25 | + | ||
| 26 | + private FTPClient connectFtpServer() { | ||
| 27 | + FTPClient ftpClient = new FTPClient(); | ||
| 28 | + ftpClient.setConnectTimeout(1000 * 60); | ||
| 29 | + ftpClient.setControlEncoding("utf-8"); | ||
| 30 | + ftpClient.enterLocalPassiveMode(); | ||
| 31 | + | ||
| 32 | + int retryTimes = ftpConfigBean.getRetryTimes(); // 假设getRetryTimes方法返回int类型的重试次数,-1表示无限重试 | ||
| 33 | + boolean isConnected = false; | ||
| 34 | + int attempts = 0; | ||
| 35 | + | ||
| 36 | + while (!isConnected && (retryTimes == -1 || attempts < retryTimes)) { | ||
| 37 | + try { | ||
| 38 | + int replyCode; | ||
| 39 | + ftpClient.connect(ftpConfigBean.getHost()); | ||
| 40 | + ftpClient.login(ftpConfigBean.getUsername(), ftpConfigBean.getPassword()); | ||
| 41 | + replyCode = ftpClient.getReplyCode(); | ||
| 42 | + | ||
| 43 | + if (!FTPReply.isPositiveCompletion(replyCode)) { | ||
| 44 | + log.info("连接FTP服务器 {} 失败", ftpConfigBean.getHost()); | ||
| 45 | + ftpClient.disconnect(); | ||
| 46 | + attempts++; | ||
| 47 | + if (retryTimes != -1) { | ||
| 48 | + log.info("第 {} 次尝试连接失败, 将重新连接", attempts); | ||
| 49 | + } | ||
| 50 | + continue; // 连接不成功,继续循环 | ||
| 51 | + } | ||
| 52 | + isConnected = true; | ||
| 53 | + log.info("replyCode:{}", replyCode); | ||
| 54 | + } catch (IOException e) { | ||
| 55 | + log.error("连接失败: {}", e.toString()); | ||
| 56 | + attempts++; | ||
| 57 | + if (retryTimes != -1) { | ||
| 58 | + log.info("第 {} 次尝试连接失败, 错误信息: {}", attempts, e.getMessage()); | ||
| 59 | + } | ||
| 60 | + try { | ||
| 61 | + // 等待一段时间再重试 | ||
| 62 | + Thread.sleep(ftpConfigBean.getRetryWaitTimes()); | ||
| 63 | + } catch (InterruptedException ie) { | ||
| 64 | + Thread.currentThread().interrupt(); | ||
| 65 | + } | ||
| 66 | + } | ||
| 67 | + } | ||
| 68 | + if (!isConnected) { | ||
| 69 | + log.error("无法连接到FTP服务器,已达到最大重试次数"); | ||
| 70 | + return null; | ||
| 71 | + } | ||
| 72 | + return ftpClient; | ||
| 73 | + } | ||
| 74 | +} |
src/main/java/com/genersoft/iot/vmp/vmanager/util/RsRequestUtils.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.vmanager.util; | ||
| 2 | + | ||
| 3 | +import cn.hutool.http.HttpUtil; | ||
| 4 | +import org.slf4j.Logger; | ||
| 5 | +import org.slf4j.LoggerFactory; | ||
| 6 | + | ||
| 7 | +import java.security.MessageDigest; | ||
| 8 | +import java.util.*; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * RS 接口调用工具类 | ||
| 12 | + * Created by panzhao on 2017/8/2. | ||
| 13 | + */ | ||
| 14 | +public class RsRequestUtils { | ||
| 15 | + | ||
| 16 | + private static String password; | ||
| 17 | + | ||
| 18 | + static { | ||
| 19 | + password = "f8267b7bc5e51994bab57c8e8884f203609d1dc3"; | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + static Logger logger = LoggerFactory.getLogger(RsRequestUtils.class); | ||
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * 生成参数字符串 | ||
| 26 | + * | ||
| 27 | + * @return | ||
| 28 | + */ | ||
| 29 | + public static String getParams() { | ||
| 30 | + String rs = ""; | ||
| 31 | + try { | ||
| 32 | + String nonce = getNonce(6); | ||
| 33 | + long t = System.currentTimeMillis(); | ||
| 34 | + | ||
| 35 | + Map<String, String> map = new HashMap<>(); | ||
| 36 | + map.put("password", password); | ||
| 37 | + map.put("timestamp", t + ""); | ||
| 38 | + map.put("nonce", nonce); | ||
| 39 | + | ||
| 40 | + String sign = getSHA1(map); | ||
| 41 | + | ||
| 42 | + rs = "?password=" + password + "×tamp=" + t + "&nonce=" + nonce + "&sign=" + sign; | ||
| 43 | + } catch (Exception e) { | ||
| 44 | + logger.error("", e); | ||
| 45 | + } | ||
| 46 | + return rs; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + /** | ||
| 50 | + * 生成参数字符串 | ||
| 51 | + * | ||
| 52 | + * @return | ||
| 53 | + */ | ||
| 54 | + public static String getParams(Map<String, String> paramMap) { | ||
| 55 | + StringBuilder rs = new StringBuilder("?"); | ||
| 56 | + try { | ||
| 57 | + String nonce = getNonce(6); | ||
| 58 | + long t = System.currentTimeMillis(); | ||
| 59 | + | ||
| 60 | + paramMap.put("password", password); | ||
| 61 | + paramMap.put("timestamp", t + ""); | ||
| 62 | + paramMap.put("nonce", nonce); | ||
| 63 | + | ||
| 64 | + String sign = getSHA1(paramMap); | ||
| 65 | + paramMap.put("sign", sign); | ||
| 66 | + | ||
| 67 | + Set<String> ks = paramMap.keySet(); | ||
| 68 | + for (String k : ks) { | ||
| 69 | + rs.append(k + "=" + paramMap.get(k) + "&"); | ||
| 70 | + } | ||
| 71 | + rs.deleteCharAt(rs.length() - 1); | ||
| 72 | + } catch (Exception e) { | ||
| 73 | + logger.error("", e); | ||
| 74 | + } | ||
| 75 | + return rs.toString(); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + /** | ||
| 79 | + * 生成随机字符串 | ||
| 80 | + * | ||
| 81 | + * @return | ||
| 82 | + */ | ||
| 83 | + public static String getNonce(int length) { | ||
| 84 | + String base = "abcdefghijklmnopqrstuvwxyz0123456789"; | ||
| 85 | + Random random = new Random(); | ||
| 86 | + StringBuffer sb = new StringBuffer(); | ||
| 87 | + for (int i = 0; i < length; i++) { | ||
| 88 | + int number = random.nextInt(base.length()); | ||
| 89 | + sb.append(base.charAt(number)); | ||
| 90 | + } | ||
| 91 | + return sb.toString(); | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + private static String getSHA1(Map<String, String> map) throws Exception { | ||
| 95 | + try { | ||
| 96 | + String[] array = new String[map.size()]; | ||
| 97 | + map.values().toArray(array); | ||
| 98 | + StringBuffer sb = new StringBuffer(); | ||
| 99 | + // 字符串排序 | ||
| 100 | + Arrays.sort(array); | ||
| 101 | + for (int i = 0; i < array.length; i++) { | ||
| 102 | + sb.append(array[i]); | ||
| 103 | + } | ||
| 104 | + String str = sb.toString(); | ||
| 105 | + // SHA1签名生成 | ||
| 106 | + MessageDigest md = MessageDigest.getInstance("SHA-1"); | ||
| 107 | + md.update(str.getBytes()); | ||
| 108 | + byte[] digest = md.digest(); | ||
| 109 | + StringBuffer hexStr = new StringBuffer(); | ||
| 110 | + String shaHex; | ||
| 111 | + for (int i = 0; i < digest.length; i++) { | ||
| 112 | + shaHex = Integer.toHexString(digest[i] & 0xFF); | ||
| 113 | + if (shaHex.length() < 2) { | ||
| 114 | + hexStr.append(0); | ||
| 115 | + } | ||
| 116 | + hexStr.append(shaHex); | ||
| 117 | + } | ||
| 118 | + return hexStr.toString(); | ||
| 119 | + } catch (Exception e) { | ||
| 120 | + throw e; | ||
| 121 | + } | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + public static void main(String[] args) { | ||
| 125 | +// StringBuilder rs = null; | ||
| 126 | +// try { | ||
| 127 | +// rs = HttpClientUtils.get("http://106.14.30.180:9089/webservice/rest/schedule_real/execs?password=e126853c7f6f43b4857fa8dfe3b28b5d90be9e68×tamp=1587101390953&nonce=z5uefd&sign=cbdc60ec931cdf8f4b45104ddd6809a16f82e76f"); | ||
| 128 | +// } catch (Exception e) { | ||
| 129 | +// e.printStackTrace(); | ||
| 130 | +// } | ||
| 131 | + String lineInfoUrl = "http://58.34.47.74:9089/webservice/rest/line/company/55" + RsRequestUtils.getParams(); | ||
| 132 | + String lineInfoJson = HttpUtil.get(lineInfoUrl); | ||
| 133 | + System.out.println(lineInfoUrl); | ||
| 134 | +// System.out.println(rs.toString()); | ||
| 135 | +// List<ScheduleRealInfo> list = JSONArray.parseArray(rs.toString(), ScheduleRealInfo.class); | ||
| 136 | +// System.out.println(list.size()); | ||
| 137 | + | ||
| 138 | + } | ||
| 139 | +} |
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java
src/main/resources/application-dev100.yml
| @@ -31,7 +31,7 @@ spring: | @@ -31,7 +31,7 @@ spring: | ||
| 31 | master: | 31 | master: |
| 32 | type: com.zaxxer.hikari.HikariDataSource | 32 | type: com.zaxxer.hikari.HikariDataSource |
| 33 | driver-class-name: com.mysql.cj.jdbc.Driver | 33 | driver-class-name: com.mysql.cj.jdbc.Driver |
| 34 | - url: jdbc:mysql://192.168.169.100:3306/wvp4?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=TRUE&serverTimezone=PRC&useSSL=false&allowMultiQueries=true | 34 | + url: jdbc:mysql://192.168.169.100:3306/wvp4?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=TRUE&serverTimezone=PRC&useSSL=false&allowMultiQueries=true&sessionVariables=sql_mode='NO_ENGINE_SUBSTITUTION'&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull |
| 35 | username: root | 35 | username: root |
| 36 | password: guzijian | 36 | password: guzijian |
| 37 | hikari: | 37 | hikari: |
| @@ -141,13 +141,14 @@ tuohua: | @@ -141,13 +141,14 @@ tuohua: | ||
| 141 | historyUdpPort: 9999 | 141 | historyUdpPort: 9999 |
| 142 | ip : 61.169.120.202 | 142 | ip : 61.169.120.202 |
| 143 | jt1078: | 143 | jt1078: |
| 144 | - ports: 9101,9600 | 144 | + ports: 49101,49200 |
| 145 | port: 9100 | 145 | port: 9100 |
| 146 | httpPort: 3333 | 146 | httpPort: 3333 |
| 147 | addPortVal: 0 | 147 | addPortVal: 0 |
| 148 | pushURL: http://127.0.0.1:3333/new/server/{pushKey}/{port}/{httpPort} | 148 | pushURL: http://127.0.0.1:3333/new/server/{pushKey}/{port}/{httpPort} |
| 149 | stopPushURL: http://127.0.0.1:3333/stop/channel/{pushKey}/{port}/{httpPort} | 149 | stopPushURL: http://127.0.0.1:3333/stop/channel/{pushKey}/{port}/{httpPort} |
| 150 | url: http://192.168.168.152:8100/device/{0} | 150 | url: http://192.168.168.152:8100/device/{0} |
| 151 | + new_url: http://192.168.168.152:8100/device | ||
| 151 | historyListPort: 9205 | 152 | historyListPort: 9205 |
| 152 | playHistoryPort: 9201 | 153 | playHistoryPort: 9201 |
| 153 | sendPort: 9101 | 154 | sendPort: 9101 |
| @@ -159,3 +160,31 @@ tuohua: | @@ -159,3 +160,31 @@ tuohua: | ||
| 159 | url: http://192.168.169.100:3333/video/{stream}.flv | 160 | url: http://192.168.169.100:3333/video/{stream}.flv |
| 160 | playURL: /play/wasm/ws%3A%2F%2F{ip}%3A{port}%2Fschedule%2F{sim}-{channel}.live.flv%3FcallId%{publickey} | 161 | playURL: /play/wasm/ws%3A%2F%2F{ip}%3A{port}%2Fschedule%2F{sim}-{channel}.live.flv%3FcallId%{publickey} |
| 161 | 162 | ||
| 163 | +ftp: | ||
| 164 | + basePath: /wvp-local | ||
| 165 | + host: 192.168.169.100 | ||
| 166 | + httpPath: ftp://192.168.169.100 | ||
| 167 | + filePathPrefix: http://192.168.169.100:10021/wvp-local | ||
| 168 | + password: ftpadmin | ||
| 169 | + port: 21 | ||
| 170 | + username: ftp@123 | ||
| 171 | + retryTimes: 5 | ||
| 172 | + retryWaitTimes: 3000 | ||
| 173 | + | ||
| 174 | +forest: | ||
| 175 | + backend: okhttp3 # 后端HTTP框架(默认为 okhttp3) | ||
| 176 | + max-connections: 1000 # 连接池最大连接数(默认为 500) | ||
| 177 | + max-route-connections: 500 # 每个路由的最大连接数(默认为 500) | ||
| 178 | + max-request-queue-size: 100 # [自v1.5.22版本起可用] 最大请求等待队列大小 | ||
| 179 | + max-async-thread-size: 300 # [自v1.5.21版本起可用] 最大异步线程数 | ||
| 180 | + max-async-queue-size: 16 # [自v1.5.22版本起可用] 最大异步线程池队列大小 | ||
| 181 | + timeout: 3000 # [已不推荐使用] 请求超时时间,单位为毫秒(默认为 3000) | ||
| 182 | + connect-timeout: 3000 # 连接超时时间,单位为毫秒(默认为 timeout) | ||
| 183 | + read-timeout: 3000 # 数据读取超时时间,单位为毫秒(默认为 timeout) | ||
| 184 | + max-retry-count: 0 # 请求失败后重试次数(默认为 0 次不重试) | ||
| 185 | + # ssl-protocol: TLS # 单向验证的HTTPS的默认TLS协议(默认为 TLS) | ||
| 186 | + log-enabled: true # 打开或关闭日志(默认为 true) | ||
| 187 | + log-request: true # 打开/关闭Forest请求日志(默认为 true) | ||
| 188 | + log-response-status: true # 打开/关闭Forest响应状态日志(默认为 true) | ||
| 189 | + log-response-content: true # 打开/关闭Forest响应内容日志(默认为 false) | ||
| 190 | +# async-mode: platform # [自v1.5.27版本起可用] 异步模式(默认为 platform) |
src/test/java/com/genersoft/iot/vmp/jt1078/JT1078ServerTest.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.jt1078; | ||
| 2 | - | ||
| 3 | -import com.genersoft.iot.vmp.jt1078.cmd.JT1078Template; | ||
| 4 | -import com.genersoft.iot.vmp.jt1078.codec.netty.TcpServer; | ||
| 5 | -import com.genersoft.iot.vmp.jt1078.proc.response.J9102; | ||
| 6 | -import com.genersoft.iot.vmp.jt1078.proc.response.J9201; | ||
| 7 | -import com.genersoft.iot.vmp.jt1078.proc.response.J9202; | ||
| 8 | -import com.genersoft.iot.vmp.jt1078.proc.response.J9205; | ||
| 9 | - | ||
| 10 | -import java.util.Scanner; | ||
| 11 | - | ||
| 12 | -/** | ||
| 13 | - * @author QingtaiJiang | ||
| 14 | - * @date 2023/4/28 14:22 | ||
| 15 | - * @email qingtaij@163.com | ||
| 16 | - */ | ||
| 17 | -public class JT1078ServerTest { | ||
| 18 | - | ||
| 19 | - private static final JT1078Template jt1078Template = new JT1078Template(); | ||
| 20 | - | ||
| 21 | - public static void main(String[] args) { | ||
| 22 | - System.out.println("Starting jt1078 server..."); | ||
| 23 | - TcpServer tcpServer = new TcpServer(21078); | ||
| 24 | - tcpServer.start(); | ||
| 25 | - System.out.println("Start jt1078 server success!"); | ||
| 26 | - | ||
| 27 | - | ||
| 28 | - Scanner s = new Scanner(System.in); | ||
| 29 | - while (true) { | ||
| 30 | - String code = s.nextLine(); | ||
| 31 | - switch (code) { | ||
| 32 | - case "1": | ||
| 33 | - test9102(); | ||
| 34 | - break; | ||
| 35 | - case "2": | ||
| 36 | - test9201(); | ||
| 37 | - break; | ||
| 38 | - case "3": | ||
| 39 | - test9202(); | ||
| 40 | - break; | ||
| 41 | - case "4": | ||
| 42 | - test9205(); | ||
| 43 | - break; | ||
| 44 | - default: | ||
| 45 | - break; | ||
| 46 | - } | ||
| 47 | - } | ||
| 48 | - } | ||
| 49 | - | ||
| 50 | - private static void test9102() { | ||
| 51 | - J9102 j9102 = new J9102(); | ||
| 52 | - j9102.setChannel(1); | ||
| 53 | - j9102.setCommand(0); | ||
| 54 | - j9102.setCloseType(0); | ||
| 55 | - j9102.setStreamType(0); | ||
| 56 | - | ||
| 57 | - String s = jt1078Template.stopLive("18864197066", j9102, 6); | ||
| 58 | - System.out.println(s); | ||
| 59 | - } | ||
| 60 | - | ||
| 61 | - private static void test9201() { | ||
| 62 | - J9201 j9201 = new J9201(); | ||
| 63 | - j9201.setIp("192.168.1.1"); | ||
| 64 | - j9201.setChannel(1); | ||
| 65 | - j9201.setTcpPort(7618); | ||
| 66 | - j9201.setUdpPort(7618); | ||
| 67 | - j9201.setType(0); | ||
| 68 | - j9201.setRate(0); | ||
| 69 | - j9201.setStorageType(0); | ||
| 70 | - j9201.setPlaybackType(0); | ||
| 71 | - j9201.setPlaybackSpeed(0); | ||
| 72 | - j9201.setStartTime("230428134100"); | ||
| 73 | - j9201.setEndTime("230428134200"); | ||
| 74 | - | ||
| 75 | - String s = jt1078Template.startBackLive("18864197066", j9201, 6); | ||
| 76 | - System.out.println(s); | ||
| 77 | - } | ||
| 78 | - | ||
| 79 | - private static void test9202() { | ||
| 80 | - J9202 j9202 = new J9202(); | ||
| 81 | - | ||
| 82 | - j9202.setChannel(1); | ||
| 83 | - j9202.setPlaybackType(2); | ||
| 84 | - j9202.setPlaybackSpeed(0); | ||
| 85 | - j9202.setPlaybackTime("230428134100"); | ||
| 86 | - | ||
| 87 | - String s = jt1078Template.controlBackLive("18864197066", j9202, 6); | ||
| 88 | - System.out.println(s); | ||
| 89 | - } | ||
| 90 | - | ||
| 91 | - private static void test9205() { | ||
| 92 | - J9205 j9205 = new J9205(); | ||
| 93 | - j9205.setChannelId(1); | ||
| 94 | - j9205.setStartTime("230428134100"); | ||
| 95 | - j9205.setEndTime("230428134100"); | ||
| 96 | - j9205.setMediaType(0); | ||
| 97 | - j9205.setStreamType(0); | ||
| 98 | - j9205.setStorageType(0); | ||
| 99 | - | ||
| 100 | - String s = jt1078Template.queryBackTime("18864197066", j9205, 6); | ||
| 101 | - System.out.println(s); | ||
| 102 | - } | ||
| 103 | -} |
web_src/config/index.js
| @@ -11,14 +11,14 @@ module.exports = { | @@ -11,14 +11,14 @@ module.exports = { | ||
| 11 | assetsPublicPath: "/", | 11 | assetsPublicPath: "/", |
| 12 | proxyTable: { | 12 | proxyTable: { |
| 13 | "/debug": { | 13 | "/debug": { |
| 14 | - target: "http://127.0.0.1:28080", | 14 | + target: "http://127.0.0.1:16030", |
| 15 | changeOrigin: true, | 15 | changeOrigin: true, |
| 16 | pathRewrite: { | 16 | pathRewrite: { |
| 17 | "^/debug": "/", | 17 | "^/debug": "/", |
| 18 | }, | 18 | }, |
| 19 | }, | 19 | }, |
| 20 | "/static/snap": { | 20 | "/static/snap": { |
| 21 | - target: "http://127.0.0.1:28080", | 21 | + target: "http://127.0.0.1:16030", |
| 22 | changeOrigin: true, | 22 | changeOrigin: true, |
| 23 | // pathRewrite: { | 23 | // pathRewrite: { |
| 24 | // '^/static/snap': '/static/snap' | 24 | // '^/static/snap': '/static/snap' |
web_src/src/components/DeviceList1078.vue
| 1 | <template> | 1 | <template> |
| 2 | - <div id="devicePosition" style="width:100vw; height: 91vh"> | 2 | + <div v-loading="loading" id="devicePosition" style="width:100vw; height: 91vh"> |
| 3 | <el-container v-loading="loading" style="height: 91vh;" element-loading-text="拼命加载中"> | 3 | <el-container v-loading="loading" style="height: 91vh;" element-loading-text="拼命加载中"> |
| 4 | <el-aside width="300px" style="background-color: #ffffff"> | 4 | <el-aside width="300px" style="background-color: #ffffff"> |
| 5 | - <div class="device-tree-main-box"> | ||
| 6 | - <div id="DeviceTree" style="width: 100%;height: 100%; background-color: #FFFFFF; overflow: auto"> | ||
| 7 | - <el-container> | ||
| 8 | - <el-header>设备列表</el-header> | ||
| 9 | - <el-main style="background-color: #ffffff;"> | ||
| 10 | - <tree :nodes="nodes" @onClick="onClick" @onCheck="onCheck" @onExpand="onExpand" | ||
| 11 | - @onRightClick="treeRightMenuFun" @onCreated="handleCreated" :props="defaultProps"/> | ||
| 12 | - </el-main> | ||
| 13 | - </el-container> | ||
| 14 | - </div> | ||
| 15 | - </div> | 5 | + <device1078-tree :tree-data="sourceValue" @node-click="nodeClick"></device1078-tree> |
| 16 | </el-aside> | 6 | </el-aside> |
| 17 | <el-container> | 7 | <el-container> |
| 18 | <el-header height="5vh" style="text-align: left;font-size: 17px;line-height:5vh;width:90%"> | 8 | <el-header height="5vh" style="text-align: left;font-size: 17px;line-height:5vh;width:90%"> |
| 19 | - | ||
| 20 | <i class="el-icon-s-platform btn" :class="{active:spilt==1}" @click="spiltClickFun(1)"/> | 9 | <i class="el-icon-s-platform btn" :class="{active:spilt==1}" @click="spiltClickFun(1)"/> |
| 21 | <i class="el-icon-menu btn" :class="{active:spilt==4}" @click="spiltClickFun(4)"/> | 10 | <i class="el-icon-menu btn" :class="{active:spilt==4}" @click="spiltClickFun(4)"/> |
| 22 | <i class="el-icon-s-grid btn" :class="{active:spilt==9}" @click="spiltClickFun(9)"/> | 11 | <i class="el-icon-s-grid btn" :class="{active:spilt==9}" @click="spiltClickFun(9)"/> |
| 23 | <i class="el-icon-full-screen btn" :class="{active:spilt==12}" @click="spiltClickFun(12)"/> | 12 | <i class="el-icon-full-screen btn" :class="{active:spilt==12}" @click="spiltClickFun(12)"/> |
| 24 | - | ||
| 25 | <el-button size="mini" style="margin-left: 15px;" @click="oneClickPlayback()">一键播放车辆视频</el-button> | 13 | <el-button size="mini" style="margin-left: 15px;" @click="oneClickPlayback()">一键播放车辆视频</el-button> |
| 26 | <el-button size="mini" style="margin-left: 15px;" @click="closeSelectItem()">关闭选中画面流</el-button> | 14 | <el-button size="mini" style="margin-left: 15px;" @click="closeSelectItem()">关闭选中画面流</el-button> |
| 27 | <el-button size="mini" style="margin-left: 15px;" @click="closeSelectCarItem()">一键关闭选中车辆流</el-button> | 15 | <el-button size="mini" style="margin-left: 15px;" @click="closeSelectCarItem()">一键关闭选中车辆流</el-button> |
| 28 | - <el-button size="mini" style="margin-left: 15px;" @click="inspectionsDialog">视屏巡查</el-button> | 16 | + <el-button size="mini" style="margin-left: 15px;" @click="inspectionsDialog" v-if="patrolValue" type="danger"> |
| 17 | + 视屏巡查中 | ||
| 18 | + </el-button> | ||
| 19 | + <el-button size="mini" style="margin-left: 15px;" @click="inspectionsDialog" v-else>视屏巡查</el-button> | ||
| 29 | </el-header> | 20 | </el-header> |
| 30 | - | ||
| 31 | <el-main style="padding: 0;"> | 21 | <el-main style="padding: 0;"> |
| 32 | - <div class="scroll-container" style="width: 100%;height: 85vh;display: flex;flex-wrap: wrap;background-color: #000;"> | 22 | + <div class="scroll-container" |
| 23 | + style="width: 100%;height: 85vh;display: flex;flex-wrap: wrap;background-color: #000;"> | ||
| 33 | <div v-for="i in spilt" :key="i" class="play-box" | 24 | <div v-for="i in spilt" :key="i" class="play-box" |
| 34 | :style="liveStyle" :class="{redborder:playerIdx == (i-1)}" | 25 | :style="liveStyle" :class="{redborder:playerIdx == (i-1)}" |
| 35 | @click="playerIdx = (i-1)"> | 26 | @click="playerIdx = (i-1)"> |
| @@ -58,18 +49,55 @@ | @@ -58,18 +49,55 @@ | ||
| 58 | 49 | ||
| 59 | <el-dialog title="视屏巡查设置" width="600" append-to-body | 50 | <el-dialog title="视屏巡查设置" width="600" append-to-body |
| 60 | :close-on-click-modal="false" | 51 | :close-on-click-modal="false" |
| 61 | - :visible.sync="showVideoDialog" > | ||
| 62 | - <tree-transfer | ||
| 63 | - style="text-align: left; display: inline-block" | ||
| 64 | - :to_data="targetValue" | ||
| 65 | - :filter="true" | ||
| 66 | - :title="['源列表', '巡查列表']" | ||
| 67 | - @change="handleChange" | ||
| 68 | - :from_data="sourceValue"> | ||
| 69 | - </tree-transfer> | 52 | + :visible.sync="showVideoDialog" v-loading="loading"> |
| 53 | + <el-card class="box-card"> | ||
| 54 | + <tree-transfer | ||
| 55 | + :disabled="patrolValue" | ||
| 56 | + style="text-align: left; display: inline-block;" | ||
| 57 | + :to_data="targetValue" | ||
| 58 | + :defaultExpandedKeys="expandedKeys" | ||
| 59 | + node_key="id" | ||
| 60 | + :filter="true" | ||
| 61 | + :title="['源列表', '巡查列表']" | ||
| 62 | + :from_data="sourceValue" | ||
| 63 | + :defaultProps="treeProps" | ||
| 64 | + :filter-node="filterNode" | ||
| 65 | + class="inspections-tree" | ||
| 66 | + height="500px"> | ||
| 67 | + </tree-transfer> | ||
| 68 | + </el-card> | ||
| 69 | + <el-card class="box-card"> | ||
| 70 | + <div slot="header" class="clearfix"> | ||
| 71 | + <span style="font-size: math">巡查时间间隔</span> | ||
| 72 | + </div> | ||
| 73 | + <el-time-select | ||
| 74 | + v-model="timerTime" | ||
| 75 | + :picker-options="{ | ||
| 76 | + start: '00:30', | ||
| 77 | + step: '00:30', | ||
| 78 | + end: '5:00' | ||
| 79 | + }" | ||
| 80 | + placeholder="选择巡查时间" | ||
| 81 | + :disabled="patrolValue"> | ||
| 82 | + </el-time-select> | ||
| 83 | + </el-card> | ||
| 84 | + <el-card class="box-card"> | ||
| 85 | + <div slot="header" class="clearfix"> | ||
| 86 | + <span style="font-size: math">巡查宫格数量</span> | ||
| 87 | + </div> | ||
| 88 | + <el-select v-model="patrolCell" placeholder="placeholder" :disabled="patrolValue"> | ||
| 89 | + <el-option | ||
| 90 | + v-for="item in patrolCellList" | ||
| 91 | + :key="item" | ||
| 92 | + :label="item" | ||
| 93 | + :value="item"> | ||
| 94 | + </el-option> | ||
| 95 | + </el-select> | ||
| 96 | + </el-card> | ||
| 70 | <div slot="footer" class="dialog-footer"> | 97 | <div slot="footer" class="dialog-footer"> |
| 71 | - <el-button type="primary" @click="submitForm">确 定</el-button> | ||
| 72 | - <el-button @click="cancel">取 消</el-button> | 98 | + <el-button type="danger" v-if="patrolValue" @click="closeInspections">关闭</el-button> |
| 99 | + <el-button type="primary" v-else @click="openInspections">开启</el-button> | ||
| 100 | + <el-button @click="showVideoDialog = false">取 消</el-button> | ||
| 73 | </div> | 101 | </div> |
| 74 | </el-dialog> | 102 | </el-dialog> |
| 75 | </div> | 103 | </div> |
| @@ -80,34 +108,60 @@ import uiHeader from "../layout/UiHeader.vue"; | @@ -80,34 +108,60 @@ import uiHeader from "../layout/UiHeader.vue"; | ||
| 80 | import player from './common/jessibuca.vue'; | 108 | import player from './common/jessibuca.vue'; |
| 81 | import DeviceTree from './common/DeviceTree.vue' | 109 | import DeviceTree from './common/DeviceTree.vue' |
| 82 | import treeTransfer from "el-tree-transfer"; | 110 | import treeTransfer from "el-tree-transfer"; |
| 111 | +import {parseTime} from "../../utils/ruoyi"; | ||
| 112 | +import Device1078Tree from "./JT1078Components/deviceList/Device1078Tree.vue"; | ||
| 113 | + | ||
| 83 | export default { | 114 | export default { |
| 84 | name: "live", | 115 | name: "live", |
| 85 | components: { | 116 | components: { |
| 117 | + Device1078Tree, | ||
| 86 | uiHeader, player, DeviceTree, tree, treeTransfer | 118 | uiHeader, player, DeviceTree, tree, treeTransfer |
| 87 | }, | 119 | }, |
| 88 | data() { | 120 | data() { |
| 89 | return { | 121 | return { |
| 90 | - //穿梭框数据-----------↓ | 122 | + //车辆列表过滤 |
| 123 | + filterText: '', | ||
| 124 | + //穿梭框巡查数据-----------↓ | ||
| 125 | + //穿梭框默认展开 | ||
| 126 | + expandedKeys: [], | ||
| 127 | + // 批次获取器 | ||
| 128 | + batchFetcher: null, | ||
| 91 | //源列表数据 | 129 | //源列表数据 |
| 92 | sourceValue: [], | 130 | sourceValue: [], |
| 131 | + //原始sim列表 (sim对象) | ||
| 132 | + simList: [], | ||
| 93 | //目标列表数据 | 133 | //目标列表数据 |
| 94 | targetValue: [], | 134 | targetValue: [], |
| 135 | + //巡查播放原始列表 | ||
| 136 | + lastTargetValue: [], | ||
| 137 | + //巡查过滤列表 (sim) | ||
| 138 | + lastTargetValueFilter: [], | ||
| 139 | + //现在正在播放的列表 | ||
| 140 | + nowPlayArray: [], | ||
| 95 | //prop参数 | 141 | //prop参数 |
| 96 | - treeProps:{ | 142 | + treeProps: { |
| 97 | children: 'children', | 143 | children: 'children', |
| 98 | - label: 'label', | ||
| 99 | - name: 'name' | 144 | + label: 'name', |
| 145 | + disabled: 'disabled', | ||
| 100 | }, | 146 | }, |
| 101 | //巡查按钮 | 147 | //巡查按钮 |
| 102 | patrolValue: false, | 148 | patrolValue: false, |
| 103 | - //巡查数据定时器 | ||
| 104 | - carInfoTimeout: '', | 149 | + //巡查宫格数量 |
| 150 | + patrolCell: 9, | ||
| 151 | + //巡查宫格下拉框数据 | ||
| 152 | + patrolCellList: [1, 4, 9, 12], | ||
| 153 | + //巡查时间 | ||
| 154 | + timerTime: '00:30', | ||
| 105 | //巡查定时器 | 155 | //巡查定时器 |
| 106 | - timer : '', | 156 | + fetchInterval: null, |
| 107 | //上线车辆 | 157 | //上线车辆 |
| 108 | onlineCar: new Map(), | 158 | onlineCar: new Map(), |
| 159 | + //车辆数据定时器 | ||
| 160 | + carInfoTimeout: null, | ||
| 109 | //车载key集合 | 161 | //车载key集合 |
| 110 | onlineCarKeys: [], | 162 | onlineCarKeys: [], |
| 163 | + //树节点对象 | ||
| 164 | + simNodeData: null, | ||
| 111 | videoUrl: [''], | 165 | videoUrl: [''], |
| 112 | videoUrlHistory: "", | 166 | videoUrlHistory: "", |
| 113 | spilt: 1,//分屏 | 167 | spilt: 1,//分屏 |
| @@ -167,6 +221,7 @@ export default { | @@ -167,6 +221,7 @@ export default { | ||
| 167 | }, | 221 | }, |
| 168 | created() { | 222 | created() { |
| 169 | this.checkPlayByParam(); | 223 | this.checkPlayByParam(); |
| 224 | + this.getCarInfoBuffer() | ||
| 170 | }, | 225 | }, |
| 171 | beforeDestroy() { | 226 | beforeDestroy() { |
| 172 | if (!this.isEmpty(this.timer)) { | 227 | if (!this.isEmpty(this.timer)) { |
| @@ -224,85 +279,493 @@ export default { | @@ -224,85 +279,493 @@ export default { | ||
| 224 | } | 279 | } |
| 225 | }, | 280 | }, |
| 226 | methods: { | 281 | methods: { |
| 227 | - handleChange(value, direction, movedKeys) { | ||
| 228 | - console.log(value, direction, movedKeys); | 282 | + /** |
| 283 | + * 统计树节点下一级有多少在线数量 | ||
| 284 | + */ | ||
| 285 | + statisticsOnline(data) { | ||
| 286 | + for (let i in data) { | ||
| 287 | + console.log(data[i].abnormalStatus === undefined && data[i].children && data[i].children.length > 0) | ||
| 288 | + if (data[i].abnormalStatus === undefined && data[i].children && data[i].children.length > 0) { | ||
| 289 | + data[i].onlineData = data[i].children.filter(item => item.abnormalStatus === 1); | ||
| 290 | + } | ||
| 291 | + } | ||
| 292 | + }, | ||
| 293 | + /** | ||
| 294 | + * 树点击事件 | ||
| 295 | + */ | ||
| 296 | + nodeClick(data, node) { | ||
| 297 | + if (data.children && data.children.length > 0 && data.abnormalStatus) { | ||
| 298 | + this.simNodeData = data | ||
| 299 | + } else if (data.children === undefined) { | ||
| 300 | + this.simNodeData = node.parent.data | ||
| 301 | + this.openPlay(data, this.playerIdx); | ||
| 302 | + } | ||
| 303 | + }, | ||
| 304 | + /** | ||
| 305 | + * 模糊查询树 | ||
| 306 | + */ | ||
| 307 | + filterNode(value, data) { | ||
| 308 | + console.log(data) | ||
| 309 | + if (!value) return true; | ||
| 310 | + return this.findSearKey(data, value) | ||
| 311 | + }, | ||
| 312 | + /** | ||
| 313 | + * 递归搜索父级是否包含关键字 | ||
| 314 | + */ | ||
| 315 | + findSearKey(node, key) { | ||
| 316 | + if (node.name.indexOf(key) !== -1) { | ||
| 317 | + return true; | ||
| 318 | + } else { | ||
| 319 | + if (node.parent === undefined || node.parent === null) { | ||
| 320 | + return false; | ||
| 321 | + } else { | ||
| 322 | + return this.findSearKey(node.parent, key); | ||
| 323 | + } | ||
| 324 | + } | ||
| 325 | + }, | ||
| 326 | + /** | ||
| 327 | + * 处理返回的tree数据 | ||
| 328 | + */ | ||
| 329 | + processingTreeData(data, pid, parent) { | ||
| 330 | + for (let i in data) { | ||
| 331 | + data[i].pid = pid | ||
| 332 | + data[i].parent = parent; | ||
| 333 | + if (data[i].children || (Array.isArray(data[i].children) && data[i].abnormalStatus === undefined)) { | ||
| 334 | + this.processingTreeData(data[i].children, data[i].id, data[i]); | ||
| 335 | + } else { | ||
| 336 | + data[i].name = data[i].code | ||
| 337 | + if (data[i].abnormalStatus !== 1) { | ||
| 338 | + data[i].disabled = true; | ||
| 339 | + let targetValue = this.targetValue; | ||
| 340 | + if (targetValue.length > 0) { | ||
| 341 | + this.disableItemsByName(targetValue, data[i].name); | ||
| 342 | + } | ||
| 343 | + } | ||
| 344 | + this.addChannels(data[i]) | ||
| 345 | + } | ||
| 346 | + } | ||
| 347 | + }, | ||
| 348 | + /** | ||
| 349 | + * 原始sim列表数据 (用来验证视屏巡查车辆是否在线) | ||
| 350 | + * @param data 查询后台树列表 | ||
| 351 | + */ | ||
| 352 | + processingSimList(data) { | ||
| 353 | + if (data && data.length > 0) { | ||
| 354 | + for (let i in data) { | ||
| 355 | + if (data[i].children === undefined && data[i].abnormalStatus) { | ||
| 356 | + this.simList.push(data[i]); | ||
| 357 | + } else if (data[i].children && data[i].children.length > 0) { | ||
| 358 | + this.processingSimList(data[i].children); | ||
| 359 | + } | ||
| 360 | + } | ||
| 361 | + } | ||
| 229 | }, | 362 | }, |
| 230 | - //查询车辆信息 | ||
| 231 | - getCarInfo(){ | 363 | + /** |
| 364 | + * 处理巡查列表数据 | ||
| 365 | + */ | ||
| 366 | + disableItemsByName(arr, targetName) { | ||
| 367 | + arr.forEach(item => { | ||
| 368 | + // 检查当前项是否是对象并且包含 name 属性且值为 targetName | ||
| 369 | + if (item && typeof item === 'object' && item.name === targetName) { | ||
| 370 | + item.disabled = true; | ||
| 371 | + } | ||
| 372 | + // 如果当前项有 children 属性且是数组,则递归调用自身 | ||
| 373 | + if (item && Array.isArray(item.children)) { | ||
| 374 | + this.disableItemsByName(item.children, targetName); | ||
| 375 | + } | ||
| 376 | + }); | ||
| 377 | + }, | ||
| 378 | + /** | ||
| 379 | + * 查询车辆信息 | ||
| 380 | + */ | ||
| 381 | + getCarInfoBuffer() { | ||
| 382 | + this.loading = true; | ||
| 383 | + this.getCarInfo() | ||
| 384 | + }, | ||
| 385 | + getCarInfo() { | ||
| 232 | this.$axios({ | 386 | this.$axios({ |
| 233 | method: 'get', | 387 | method: 'get', |
| 234 | url: `/api/jt1078/query/car/tree/100`, | 388 | url: `/api/jt1078/query/car/tree/100`, |
| 235 | - }).then((res) => { | 389 | + }).then(res => { |
| 236 | if (res && res.data && res.data.data) { | 390 | if (res && res.data && res.data.data) { |
| 237 | if (res.data.data.code == 1) { | 391 | if (res.data.data.code == 1) { |
| 238 | - l | ||
| 239 | - | ||
| 240 | - | ||
| 241 | - | 392 | + //处理数据 |
| 393 | + this.simList = [] | ||
| 394 | + this.processingSimList(res.data.data.result) | ||
| 395 | + this.processingTreeData(res.data.data.result, 0); | ||
| 396 | + this.statisticsOnline(res.data.data.result) | ||
| 397 | + console.log(res.data.data.result) | ||
| 398 | + this.sourceValue = res.data.data.result; | ||
| 399 | + this.loading = false | ||
| 400 | + //定时更新数据 | ||
| 401 | + let this_ = this | ||
| 242 | this.carInfoTimeout = setTimeout(function () { | 402 | this.carInfoTimeout = setTimeout(function () { |
| 243 | - this.getCarInfo() | ||
| 244 | - }, 15000); | 403 | + this_.getCarInfo() |
| 404 | + }, 45000); | ||
| 245 | } else if (res.data.data.message) { | 405 | } else if (res.data.data.message) { |
| 246 | this.$message.error(res.data.data.message); | 406 | this.$message.error(res.data.data.message); |
| 247 | } | 407 | } |
| 248 | } else { | 408 | } else { |
| 249 | this.$message.error("请求错误,请刷新再试"); | 409 | this.$message.error("请求错误,请刷新再试"); |
| 250 | } | 410 | } |
| 411 | + this.loading = false | ||
| 412 | + }).catch(error => { | ||
| 413 | + this.$message.error(error.message); | ||
| 251 | }) | 414 | }) |
| 252 | }, | 415 | }, |
| 253 | - inspectionsDialog(){ | ||
| 254 | - if (this.nodes.length < 1) { | ||
| 255 | - | ||
| 256 | - } | 416 | + /** |
| 417 | + * 打开巡查设置悬浮框 | ||
| 418 | + */ | ||
| 419 | + inspectionsDialog() { | ||
| 257 | this.showVideoDialog = true | 420 | this.showVideoDialog = true |
| 258 | }, | 421 | }, |
| 259 | - | ||
| 260 | - //视频巡查按钮改变事件 | ||
| 261 | - videoPatrolChange(newValue) { | ||
| 262 | - if (newValue) { | ||
| 263 | - this.videoPatrolStart(); | ||
| 264 | - }else { | ||
| 265 | - if (!this.isEmpty(this.timer)) { | ||
| 266 | - //关闭巡查定时器 | ||
| 267 | - clearInterval(this.timer); | ||
| 268 | - } | 422 | + /** |
| 423 | + * 添加通道 | ||
| 424 | + */ | ||
| 425 | + addChannels(data) { | ||
| 426 | + let labels = ['ADAS', 'DSM', '路况', '司机', '整车前', '中门', '倒车', '前门客流', '后面客流']; | ||
| 427 | + let children = []; | ||
| 428 | + for (let i in labels) { | ||
| 429 | + children.push({ | ||
| 430 | + id: `${data.id}_${data.sim}_${Number(i) + Number(1)}`, | ||
| 431 | + pid: data.id, | ||
| 432 | + name: labels[i], | ||
| 433 | + disabled: data.disabled, | ||
| 434 | + parent: data | ||
| 435 | + }) | ||
| 436 | + } | ||
| 437 | + data.children = children; | ||
| 438 | + }, | ||
| 439 | + /** | ||
| 440 | + * 巡查时间转换器 | ||
| 441 | + */ | ||
| 442 | + timerTimeConvertor() { | ||
| 443 | + switch (this.timerTime) { | ||
| 444 | + case "00:30": | ||
| 445 | + return 30000 | ||
| 446 | + case "01:00": | ||
| 447 | + return 30000 * 2 | ||
| 448 | + case "01:30": | ||
| 449 | + return 30000 * 3 | ||
| 450 | + case "02:00": | ||
| 451 | + return 30000 * 4 | ||
| 452 | + case "02:30": | ||
| 453 | + return 30000 * 5 | ||
| 454 | + case "03:00": | ||
| 455 | + return 30000 * 6 | ||
| 456 | + case "03:30": | ||
| 457 | + return 30000 * 7 | ||
| 458 | + case "04:00": | ||
| 459 | + return 30000 * 8 | ||
| 460 | + case "04:30": | ||
| 461 | + return 30000 * 9 | ||
| 462 | + case "05:00": | ||
| 463 | + return 30000 * 10 | ||
| 464 | + default: | ||
| 465 | + return null | ||
| 269 | } | 466 | } |
| 270 | }, | 467 | }, |
| 271 | - //开启巡查定时器 | ||
| 272 | - videoPatrolStart(itemData){ | ||
| 273 | - let onlineCarKeys = this.onlineCarKeys; | ||
| 274 | - if (!onlineCarKeys || onlineCarKeys.length === 0 ) { | ||
| 275 | - this.$message.error("没有在线设备") | 468 | + /** |
| 469 | + * 巡查开启按钮 | ||
| 470 | + */ | ||
| 471 | + openInspections() { | ||
| 472 | + let time = this.timerTimeConvertor(); | ||
| 473 | + this.spilt = this.patrolCell; | ||
| 474 | + if (time == null) { | ||
| 475 | + this.$message.error("时间选择错误 ==> [ " + this.timerTime + " ]") | ||
| 476 | + console.log("时间选择结果为 ===> [ " + time + " ]") | ||
| 477 | + } | ||
| 478 | + let targetValue = this.targetValue; | ||
| 479 | + if (targetValue === undefined || targetValue === null || targetValue.length === 0) { | ||
| 480 | + this.$message.error("未选择巡查对象") | ||
| 276 | return | 481 | return |
| 277 | } | 482 | } |
| 278 | - let count = this.onlineCarKeys.length - 1; | ||
| 279 | - setInterval(() => { | ||
| 280 | - if (itemData){ | ||
| 281 | - this.sendDevicePush(itemData); | ||
| 282 | - itemData = null | ||
| 283 | - }else { | ||
| 284 | - if (count == -1){ | ||
| 285 | - count = this.onlineCarKeys.length - 1 | 483 | + this.startFetching(time) |
| 484 | + this.showVideoDialog = false | ||
| 485 | + }, | ||
| 486 | + /** | ||
| 487 | + * 巡查树数组只获取最后一级的一维数组 | ||
| 488 | + * @param array 原数组 | ||
| 489 | + */ | ||
| 490 | + getLastElementsOfInnerArrays(array) { | ||
| 491 | + const result = []; | ||
| 492 | + | ||
| 493 | + //递归取值 | ||
| 494 | + function traverse(arr) { | ||
| 495 | + for (let item of arr) { | ||
| 496 | + let children = item.children; | ||
| 497 | + if (children !== undefined && Array.isArray(children)) { | ||
| 498 | + traverse(children); | ||
| 499 | + } else if (children === undefined) { | ||
| 500 | + result.push(item) | ||
| 501 | + } else { | ||
| 502 | + console.log("数据格式有误 ==> { " + item + " }") | ||
| 503 | + } | ||
| 504 | + } | ||
| 505 | + } | ||
| 506 | + | ||
| 507 | + //开启递归取值 | ||
| 508 | + traverse(array); | ||
| 509 | + return result; | ||
| 510 | + }, | ||
| 511 | + /** | ||
| 512 | + * 巡查关闭按钮 | ||
| 513 | + */ | ||
| 514 | + closeInspections() { | ||
| 515 | + this.stopPatrol() | ||
| 516 | + this.patrolValue = false | ||
| 517 | + clearInterval(this.fetchInterval); | ||
| 518 | + let nowPlayArray = this.nowPlayArray; | ||
| 519 | + for (let index in nowPlayArray) { | ||
| 520 | + this.setPlayUrl(null, index) | ||
| 521 | + } | ||
| 522 | + }, | ||
| 523 | + /** | ||
| 524 | + * 后台关闭视频巡查 | ||
| 525 | + */ | ||
| 526 | + stopPatrol() { | ||
| 527 | + this.$axios({ | ||
| 528 | + method: 'get', | ||
| 529 | + url: `/api/jt1078/query/stopPatrol/request/io`, | ||
| 530 | + }).then((res) => { | ||
| 531 | + if (res.data.code === 0) { | ||
| 532 | + this.$message.success("视频巡查已关闭") | ||
| 533 | + } else { | ||
| 534 | + this.$message.error("视频巡查已关闭失败, 请联系管理员"); | ||
| 535 | + } | ||
| 536 | + }); | ||
| 537 | + }, | ||
| 538 | + /** | ||
| 539 | + * 后台开启视频巡查 | ||
| 540 | + */ | ||
| 541 | + startPatrol(data) { | ||
| 542 | + this.$axios({ | ||
| 543 | + method: 'post', | ||
| 544 | + url: `/api/jt1078/query/startPatrol/request/io`, | ||
| 545 | + data: data, | ||
| 546 | + headers: { | ||
| 547 | + 'Content-Type': 'application/json', // 设置请求头 | ||
| 548 | + } | ||
| 549 | + }).then((res) => { | ||
| 550 | + if (res.data.code === 0) { | ||
| 551 | + console.log("视频巡查已开启 ===》 " + res.data.msg) | ||
| 552 | + this.$message.success("视频巡查已开启"); | ||
| 553 | + } else { | ||
| 554 | + console.log("视频巡查开启失败 ===》 " + res.data.msg) | ||
| 555 | + this.$message.error("视频巡查开启失败, 请联系管理员"); | ||
| 556 | + } | ||
| 557 | + }); | ||
| 558 | + }, | ||
| 559 | + /** | ||
| 560 | + * 巡查对话框取消按钮 | ||
| 561 | + */ | ||
| 562 | + cancel() { | ||
| 563 | + this.loading = true; | ||
| 564 | + this.targetValue = []; | ||
| 565 | + this.timerTime = '00:30' | ||
| 566 | + }, | ||
| 567 | + /** | ||
| 568 | + * 开启推流视频播放 | ||
| 569 | + */ | ||
| 570 | + openPlay(data, idxTmp, fun) { | ||
| 571 | + console.log("开启视频播放入参数据 ===》 [ " + data + " ]") | ||
| 572 | + let id = data.id; | ||
| 573 | + if (id === undefined || id === null) { | ||
| 574 | + console.log("id 内容为 :" + id) | ||
| 575 | + return; | ||
| 576 | + } | ||
| 577 | + console.log("id 内容为 :" + id) | ||
| 578 | + let arr = id.split('_'); | ||
| 579 | + if (arr === undefined || arr === null || arr.length !== 3) { | ||
| 580 | + console.log("split 内容为 :" + arr) | ||
| 581 | + return; | ||
| 582 | + } | ||
| 583 | + this.$axios({ | ||
| 584 | + method: 'get', | ||
| 585 | + url: '/api/jt1078/query/send/request/io/' + arr[1] + '/' + arr[2] | ||
| 586 | + }).then(res => { | ||
| 587 | + if (res.data.code === 0 && res.data.data) { | ||
| 588 | + let videoUrl; | ||
| 589 | + this.downloadURL = res.data.data.flv; | ||
| 590 | + if (location.protocol === "https:") { | ||
| 591 | + videoUrl = res.data.data.wss_flv; | ||
| 592 | + } else { | ||
| 593 | + videoUrl = res.data.data.ws_flv; | ||
| 286 | } | 594 | } |
| 287 | - let onlineCarKey = onlineCarKeys[count]; | ||
| 288 | - let split = onlineCarKey.split("-"); | ||
| 289 | - let onlineCar = this.onlineCar.get(split[0]) | ||
| 290 | - let sim = onlineCar.sim | ||
| 291 | - let data = { | ||
| 292 | - channelId: split[1], | ||
| 293 | - deviceId: sim, | ||
| 294 | - sim: sim | 595 | + data.playUrl = videoUrl; |
| 596 | + this.setPlayUrl(videoUrl, idxTmp); | ||
| 597 | + } else { | ||
| 598 | + if (!this.isEmpty(res.data.data) && !this.isEmpty(res.data.data.msg)) { | ||
| 599 | + this.$message.error(res.data.data.msg); | ||
| 600 | + } else { | ||
| 601 | + this.$message.error(res.data.msg); | ||
| 295 | } | 602 | } |
| 296 | - this.sendDevicePush(data); | ||
| 297 | - count --; | ||
| 298 | } | 603 | } |
| 299 | - },30000) | 604 | + if (fun) { |
| 605 | + fun(); | ||
| 606 | + } | ||
| 607 | + }) | ||
| 608 | + }, | ||
| 609 | + /** | ||
| 610 | + * 批量开启推流视频播放 | ||
| 611 | + * @param data 视频推流参数集合 Array | ||
| 612 | + */ | ||
| 613 | + // openBatchPlay(data) { | ||
| 614 | + // if (data === undefined || !Array.isArray(data)) { | ||
| 615 | + // return; | ||
| 616 | + // } | ||
| 617 | + // console.log("批量开启推流视频播放 ----》"+data) | ||
| 618 | + // let index = 0; | ||
| 619 | + // this.cycleBatchPlay(data, index) | ||
| 620 | + // }, | ||
| 621 | + cycleBatchPlay(data, index) { | ||
| 622 | + if (data === undefined || data[index] === undefined) { | ||
| 623 | + return; | ||
| 624 | + } | ||
| 625 | + let this_i = this | ||
| 626 | + this.openPlay(data[index], Number(index), function () { | ||
| 627 | + index++ | ||
| 628 | + this_i.cycleBatchPlay(data, index) | ||
| 629 | + }); | ||
| 630 | + }, | ||
| 631 | + /** | ||
| 632 | + * 发送请求验证车辆是否在线 | ||
| 633 | + * @param item | ||
| 634 | + * @returns {boolean|*} | ||
| 635 | + */ | ||
| 636 | + checkStatus(item) { | ||
| 637 | + if (this.lastTargetValueFilter.includes(item)) { | ||
| 638 | + return true | ||
| 639 | + } | ||
| 640 | + if (this.simList) { | ||
| 641 | + let find = this.simList.find(simData => simData.sim === item && simData.abnormalStatus !== 1); | ||
| 642 | + //没找到则为离线 反之在线 | ||
| 643 | + console.log("find ===> " + find) | ||
| 644 | + let f = (find === undefined) | ||
| 645 | + if (f) { | ||
| 646 | + this.lastTargetValueFilter.push(item) | ||
| 647 | + } | ||
| 648 | + return !f | ||
| 649 | + } | ||
| 650 | + return true; // 直接返回预定义的在线状态 | ||
| 651 | + }, | ||
| 652 | + /** | ||
| 653 | + * 批量验证车辆在线情况 | ||
| 654 | + * @param items | ||
| 655 | + * @returns {*} | ||
| 656 | + */ | ||
| 657 | + validateItemsOnline(items) { | ||
| 658 | + // 检查所有提供的 items 是否在线,并返回过滤后的在线 items | ||
| 659 | + const onlineItems = items.filter(item => this.checkStatus(item.id.split('_')[1])); | ||
| 660 | + if (onlineItems.length !== items.length) { | ||
| 661 | + console.warn("有车辆下线"); | ||
| 662 | + } | ||
| 663 | + this.nowPlayArray = items; | ||
| 664 | + return onlineItems; | ||
| 665 | + }, | ||
| 666 | + /** | ||
| 667 | + * 循环从数组中取出一定数量的值 | ||
| 668 | + * @param array 原数组 | ||
| 669 | + * @param batchSize 取出的数量 | ||
| 670 | + * @returns {function(): *[]} 取出的结果 | ||
| 671 | + */ | ||
| 672 | + // createBatchFetcher(array, batchSize) { | ||
| 673 | + // let currentIndex = 0; | ||
| 674 | + // array = array.slice(); // 创建数组副本以避免修改原始数组 | ||
| 675 | + // return function fetchNextBatch() { | ||
| 676 | + // const result = []; | ||
| 677 | + // for (let i = 0; i < batchSize; i++) { | ||
| 678 | + // if (currentIndex >= array.length) { | ||
| 679 | + // currentIndex = 0; // 当达到数组末尾时重置索引 | ||
| 680 | + // } | ||
| 681 | + // result.push(array[currentIndex]); | ||
| 682 | + // currentIndex++; | ||
| 683 | + // } | ||
| 684 | + // return result; | ||
| 685 | + // }; | ||
| 686 | + // }, | ||
| 687 | + createBatchFetcher(array, batchSize) { | ||
| 688 | + let currentIndex = 0; | ||
| 689 | + const originalArray = array.slice(); // 创建原始数组副本 | ||
| 690 | + | ||
| 691 | + return function fetchNextBatch() { | ||
| 692 | + const result = []; | ||
| 693 | + for (let i = 0; i < batchSize && currentIndex < originalArray.length; i++) { | ||
| 694 | + result.push(originalArray[currentIndex]); | ||
| 695 | + currentIndex++; | ||
| 696 | + } | ||
| 697 | + return result; | ||
| 698 | + }; | ||
| 699 | + }, | ||
| 700 | + /** | ||
| 701 | + * 开启视频巡查 | ||
| 702 | + * @param items 选择巡查的对象 | ||
| 703 | + * @param time | ||
| 704 | + */ | ||
| 705 | + startFetching(time) { | ||
| 706 | + this.lastTargetValue = this.getLastElementsOfInnerArrays(this.targetValue); | ||
| 707 | + console.log("targetValue ===> " + this.targetValue); | ||
| 708 | + console.log("lastTargetValue ===> " + this.lastTargetValue); | ||
| 709 | + if (!this.patrolValue && this.lastTargetValue.length > 0) { | ||
| 710 | + // 在初始化 batchFetcher 之前验证 items 是否全部在线 | ||
| 711 | + this.lastTargetValue = this.validateItemsOnline(this.lastTargetValue); | ||
| 712 | + if (this.lastTargetValue.length === 0) { | ||
| 713 | + console.warn("【车辆全部下线】请重新选择"); | ||
| 714 | + return; | ||
| 715 | + } | ||
| 716 | + this.startPatrol(this.lastTargetValue) | ||
| 717 | + this.batchFetcher = this.createBatchFetcher(this.lastTargetValue, this.spilt); | ||
| 718 | + // 立即执行一次 fetchNextBatch 并等待其完成 | ||
| 719 | + let data = this.fetchNextBatch(); | ||
| 720 | + console.log(parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}') + " 视频巡查数组 ===》 " + data); | ||
| 721 | + this.beachSendIORequest(this.convertBeachList(data)); | ||
| 722 | + // 设置定时器以定期获取批次 | ||
| 723 | + this.fetchInterval = setInterval(() => { | ||
| 724 | + let data = this.fetchNextBatch(); | ||
| 725 | + console.log(parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}') + " 视频巡查数组 ===》 " + data); | ||
| 726 | + this.beachSendIORequest(this.convertBeachList(data)); | ||
| 727 | + }, time); | ||
| 728 | + this.patrolValue = true; | ||
| 729 | + } | ||
| 730 | + }, | ||
| 731 | + /** | ||
| 732 | + * 数组转换 (方便批量发送请求) | ||
| 733 | + */ | ||
| 734 | + convertBeachList(data) { | ||
| 735 | + if (data && data.length > 0) { | ||
| 736 | + return data.map(item => item.id.split('_').slice(1).join('-')) | ||
| 737 | + } | ||
| 738 | + }, | ||
| 739 | + /** | ||
| 740 | + * 更新巡查播放列表 | ||
| 741 | + */ | ||
| 742 | + fetchNextBatch() { | ||
| 743 | + // 在每次获取批次前验证在线状态 | ||
| 744 | + const updatedItems = this.validateItemsOnline(this.lastTargetValue); | ||
| 745 | + if (updatedItems.length === 0) { | ||
| 746 | + this.$message.error("车辆已全部下线,已关闭 【视屏巡查】") | ||
| 747 | + this.stopFetching(); | ||
| 748 | + return | ||
| 749 | + } | ||
| 750 | + if (updatedItems.length !== this.lastTargetValue.length) { | ||
| 751 | + // 更新 items 和 batchFetcher | ||
| 752 | + this.lastTargetValue = updatedItems; | ||
| 753 | + this.batchFetcher = this.createBatchFetcher(updatedItems, this.spilt); | ||
| 754 | + } | ||
| 755 | + const batch = this.batchFetcher(); | ||
| 756 | + this.nowPlayArray = batch; | ||
| 757 | + return batch | ||
| 758 | + }, | ||
| 759 | + /** | ||
| 760 | + * 关闭视频巡查 | ||
| 761 | + */ | ||
| 762 | + stopFetching() { | ||
| 763 | + if (this.isFetching) { | ||
| 764 | + clearInterval(this.fetchInterval); | ||
| 765 | + this.fetchInterval = null; | ||
| 766 | + this.isFetching = false; | ||
| 767 | + } | ||
| 300 | }, | 768 | }, |
| 301 | - | ||
| 302 | - | ||
| 303 | - | ||
| 304 | - | ||
| 305 | - | ||
| 306 | destroy(idx) { | 769 | destroy(idx) { |
| 307 | this.clear(idx.substring(idx.length - 1)) | 770 | this.clear(idx.substring(idx.length - 1)) |
| 308 | }, | 771 | }, |
| @@ -313,73 +776,75 @@ export default { | @@ -313,73 +776,75 @@ export default { | ||
| 313 | this.closeLoading(); | 776 | this.closeLoading(); |
| 314 | return false; | 777 | return false; |
| 315 | } else { | 778 | } else { |
| 316 | - this.isSendDevicePush(data,this.patrolValue); | 779 | + this.isSendDevicePush(data, this.patrolValue); |
| 317 | } | 780 | } |
| 318 | } | 781 | } |
| 319 | }, | 782 | }, |
| 320 | contextMenuEvent: function (device, event, data, isCatalog) { | 783 | contextMenuEvent: function (device, event, data, isCatalog) { |
| 321 | }, | 784 | }, |
| 322 | isSendDevicePush(itemData, patrolValue) { | 785 | isSendDevicePush(itemData, patrolValue) { |
| 323 | - if (patrolValue){ | 786 | + if (patrolValue) { |
| 324 | this.videoPatrolStart(itemData); | 787 | this.videoPatrolStart(itemData); |
| 325 | - }else { | 788 | + } else { |
| 326 | this.sendDevicePush(itemData); | 789 | this.sendDevicePush(itemData); |
| 327 | } | 790 | } |
| 328 | }, | 791 | }, |
| 329 | //通知设备上传媒体流 | 792 | //通知设备上传媒体流 |
| 330 | - sendDevicePush: function (itemData, fun) { | ||
| 331 | - // if (itemData.status === 0) { | ||
| 332 | - // this.$message.error('设备离线!'); | ||
| 333 | - // return | ||
| 334 | - // } | 793 | + sendDevicePush(itemData, fun) { |
| 335 | this.save(itemData) | 794 | this.save(itemData) |
| 336 | let deviceId = itemData.deviceId; | 795 | let deviceId = itemData.deviceId; |
| 337 | - // this.isLoging = true; | ||
| 338 | let channelId = itemData.channelId; | 796 | let channelId = itemData.channelId; |
| 339 | if (this.isEmpty(deviceId)) { | 797 | if (this.isEmpty(deviceId)) { |
| 340 | this.$message.error("没有获取到sim卡,请检查设备是否接入"); | 798 | this.$message.error("没有获取到sim卡,请检查设备是否接入"); |
| 341 | this.closeLoading(); | 799 | this.closeLoading(); |
| 342 | - if (fun) {fun();} | 800 | + if (fun) { |
| 801 | + fun(); | ||
| 802 | + } | ||
| 343 | return; | 803 | return; |
| 344 | } | 804 | } |
| 345 | console.log("通知设备推流1:" + deviceId + " : " + channelId); | 805 | console.log("通知设备推流1:" + deviceId + " : " + channelId); |
| 346 | let idxTmp = this.playerIdx | 806 | let idxTmp = this.playerIdx |
| 347 | - let that = this; | ||
| 348 | this.$axios({ | 807 | this.$axios({ |
| 349 | method: 'get', | 808 | method: 'get', |
| 350 | url: '/api/jt1078/query/send/request/io/' + deviceId + '/' + channelId | 809 | url: '/api/jt1078/query/send/request/io/' + deviceId + '/' + channelId |
| 351 | - }).then(function (res) { | ||
| 352 | - if (res.data.code === 0 && res.data.data && (res.data.data.code === "1" || res.data.data.code == 1)) { | 810 | + }).then(res => { |
| 811 | + console.log(res) | ||
| 812 | + if (res.data.code === 0 && res.data.data) { | ||
| 353 | let videoUrl; | 813 | let videoUrl; |
| 354 | - that.port = res.data.data.port; | ||
| 355 | - that.httpPort = res.data.data.httpPort; | ||
| 356 | - that.stream = res.data.data.stream; | ||
| 357 | - console.log(res.data.data.data); | ||
| 358 | - if (!that.isEmpty(res.data.data.data)) { | ||
| 359 | - that.downloadURL = res.data.data.data.flv; | 814 | + this.port = res.data.data.port; |
| 815 | + this.httpPort = res.data.data.httpPort; | ||
| 816 | + this.stream = res.data.data.stream; | ||
| 817 | + console.log(res.data.data); | ||
| 818 | + if (!this.isEmpty(res.data.data)) { | ||
| 819 | + this.downloadURL = res.data.data.flv; | ||
| 360 | if (location.protocol === "https:") { | 820 | if (location.protocol === "https:") { |
| 361 | - videoUrl = res.data.data.data.wss_flv; | 821 | + videoUrl = res.data.data.wss_flv; |
| 362 | } else { | 822 | } else { |
| 363 | - videoUrl = res.data.data.data.ws_flv; | 823 | + videoUrl = res.data.data.ws_flv; |
| 364 | } | 824 | } |
| 365 | console.log(videoUrl); | 825 | console.log(videoUrl); |
| 366 | itemData.playUrl = videoUrl; | 826 | itemData.playUrl = videoUrl; |
| 367 | - that.setPlayUrl(videoUrl, idxTmp); | 827 | + this.setPlayUrl(videoUrl, idxTmp); |
| 368 | } | 828 | } |
| 369 | } else { | 829 | } else { |
| 370 | - if (!that.isEmpty(res.data.data) && !that.isEmpty(res.data.data.msg)) { | ||
| 371 | - that.$message.error(res.data.data.msg); | ||
| 372 | - } else { | ||
| 373 | - that.$message.error(res.data.msg); | ||
| 374 | - } | 830 | + this.$message.error(res.data.msg); |
| 831 | + } | ||
| 832 | + if (fun) { | ||
| 833 | + fun(); | ||
| 375 | } | 834 | } |
| 376 | - if (fun) {fun();} | ||
| 377 | }).catch(function (e) { | 835 | }).catch(function (e) { |
| 378 | - if (fun) {fun();} | 836 | + if (fun) { |
| 837 | + fun(); | ||
| 838 | + } | ||
| 379 | }).finally(() => { | 839 | }).finally(() => { |
| 380 | this.closeLoading(); | 840 | this.closeLoading(); |
| 381 | }); | 841 | }); |
| 382 | }, | 842 | }, |
| 843 | + /** | ||
| 844 | + * 播放器赋值 | ||
| 845 | + * @param url 播放内容路径 | ||
| 846 | + * @param idx 播放的id | ||
| 847 | + */ | ||
| 383 | setPlayUrl(url, idx) { | 848 | setPlayUrl(url, idx) { |
| 384 | this.$set(this.videoUrl, idx, url) | 849 | this.$set(this.videoUrl, idx, url) |
| 385 | let _this = this | 850 | let _this = this |
| @@ -394,7 +859,7 @@ export default { | @@ -394,7 +859,7 @@ export default { | ||
| 394 | } | 859 | } |
| 395 | }, | 860 | }, |
| 396 | shot(e) { | 861 | shot(e) { |
| 397 | - // console.log(e) | 862 | + console.log(e) |
| 398 | // send({code:'image',data:e}) | 863 | // send({code:'image',data:e}) |
| 399 | var base64ToBlob = function (code) { | 864 | var base64ToBlob = function (code) { |
| 400 | let parts = code.split(';base64,'); | 865 | let parts = code.split(';base64,'); |
| @@ -430,6 +895,7 @@ export default { | @@ -430,6 +895,7 @@ export default { | ||
| 430 | console.log(data); | 895 | console.log(data); |
| 431 | window.localStorage.setItem('playData', JSON.stringify(data)) | 896 | window.localStorage.setItem('playData', JSON.stringify(data)) |
| 432 | }, | 897 | }, |
| 898 | + | ||
| 433 | initTreeData() { | 899 | initTreeData() { |
| 434 | this.showLoading(); | 900 | this.showLoading(); |
| 435 | this.$axios({ | 901 | this.$axios({ |
| @@ -449,6 +915,7 @@ export default { | @@ -449,6 +915,7 @@ export default { | ||
| 449 | this.closeLoading(); | 915 | this.closeLoading(); |
| 450 | }); | 916 | }); |
| 451 | }, | 917 | }, |
| 918 | + | ||
| 452 | initDate(nodes, datas) { | 919 | initDate(nodes, datas) { |
| 453 | if (nodes && datas) { | 920 | if (nodes && datas) { |
| 454 | let len = datas.length; | 921 | let len = datas.length; |
| @@ -486,21 +953,10 @@ export default { | @@ -486,21 +953,10 @@ export default { | ||
| 486 | onClick(evt, treeId, treeNode) { | 953 | onClick(evt, treeId, treeNode) { |
| 487 | this.combationChildNode(treeNode); | 954 | this.combationChildNode(treeNode); |
| 488 | }, | 955 | }, |
| 489 | - onCheck(evt, treeId, treeNode) { | ||
| 490 | - | ||
| 491 | - }, | ||
| 492 | beforeExpand(treeId, treeNode) { | 956 | beforeExpand(treeId, treeNode) { |
| 493 | 957 | ||
| 494 | return true; | 958 | return true; |
| 495 | }, | 959 | }, |
| 496 | - onExpand(evt, treeId, treeNode) { | ||
| 497 | - this.combationChildNode(treeNode); | ||
| 498 | - }, | ||
| 499 | - handleCreated(ztreeObj) { | ||
| 500 | - this.ztreeObj = ztreeObj; | ||
| 501 | - this.ztreeObj.setting.view.nameIsHTML = true; | ||
| 502 | - | ||
| 503 | - }, | ||
| 504 | combationChildNode(treeNo) { | 960 | combationChildNode(treeNo) { |
| 505 | this.ztreeNode = treeNo; | 961 | this.ztreeNode = treeNo; |
| 506 | if (treeNo.seachChild && (treeNo.seachChild == 'true')) { | 962 | if (treeNo.seachChild && (treeNo.seachChild == 'true')) { |
| @@ -561,6 +1017,9 @@ export default { | @@ -561,6 +1017,9 @@ export default { | ||
| 561 | this.closeLoading(); | 1017 | this.closeLoading(); |
| 562 | } | 1018 | } |
| 563 | }, | 1019 | }, |
| 1020 | + /** | ||
| 1021 | + * 添加通道 | ||
| 1022 | + */ | ||
| 564 | addChannel(treeNo) { | 1023 | addChannel(treeNo) { |
| 565 | let labels = ['ADAS', 'DSM', '路况', '司机', '整车前', '中门', '倒车', '前门客流', '后面客流']; | 1024 | let labels = ['ADAS', 'DSM', '路况', '司机', '整车前', '中门', '倒车', '前门客流', '后面客流']; |
| 566 | let children = []; | 1025 | let children = []; |
| @@ -593,8 +1052,9 @@ export default { | @@ -593,8 +1052,9 @@ export default { | ||
| 593 | this.initDate(children, res.data.data.result); | 1052 | this.initDate(children, res.data.data.result); |
| 594 | this.ztreeObj.addNodes(treeNo, -1, children, true); | 1053 | this.ztreeObj.addNodes(treeNo, -1, children, true); |
| 595 | treeNo.seachChild = 'true'; | 1054 | treeNo.seachChild = 'true'; |
| 1055 | + let _this = this; | ||
| 596 | this.carPlayTimer = setTimeout(function () { | 1056 | this.carPlayTimer = setTimeout(function () { |
| 597 | - this.requestChildNode1(); | 1057 | + _this.requestChildNode1(); |
| 598 | }, 15000); | 1058 | }, 15000); |
| 599 | } else if (res.data.data.message) { | 1059 | } else if (res.data.data.message) { |
| 600 | this.$message.error(res.data.data.message); | 1060 | this.$message.error(res.data.data.message); |
| @@ -673,25 +1133,6 @@ export default { | @@ -673,25 +1133,6 @@ export default { | ||
| 673 | } | 1133 | } |
| 674 | }); | 1134 | }); |
| 675 | }, | 1135 | }, |
| 676 | - sendIORequestStop1(sim, channel, fun) { | ||
| 677 | - if (this.isEmpty(sim) || this.isEmpty(channel)) { | ||
| 678 | - console.log("sim:" + sim + ";channel:" + channel); | ||
| 679 | - if (fun) { | ||
| 680 | - fun(); | ||
| 681 | - } | ||
| 682 | - return; | ||
| 683 | - } | ||
| 684 | - this.videoUrl = ['']; | ||
| 685 | - this.$axios({ | ||
| 686 | - method: 'get', | ||
| 687 | - url: `/api/jt1078/query/send/stop/io/` + sim + "/" + channel, | ||
| 688 | - }).then((res) => { | ||
| 689 | - console.log(res); | ||
| 690 | - if (fun) { | ||
| 691 | - fun(); | ||
| 692 | - } | ||
| 693 | - }); | ||
| 694 | - }, | ||
| 695 | isEmpty(val) { | 1136 | isEmpty(val) { |
| 696 | return null == val || undefined == val || "" == val; | 1137 | return null == val || undefined == val || "" == val; |
| 697 | }, | 1138 | }, |
| @@ -713,214 +1154,81 @@ export default { | @@ -713,214 +1154,81 @@ export default { | ||
| 713 | pageObj.closeLoading(); | 1154 | pageObj.closeLoading(); |
| 714 | } | 1155 | } |
| 715 | }, | 1156 | }, |
| 716 | - searchHitoryList(){ | ||
| 717 | - if(this.isEmpty(this.carTreeNode)){ | ||
| 718 | - this.$message.error('请选择车辆'); | ||
| 719 | - return; | ||
| 720 | - } | ||
| 721 | - if(this.isEmpty(this.sim)){ | ||
| 722 | - this.$message.error('无法获取SIM卡信息,请检查设备'); | ||
| 723 | - return; | ||
| 724 | - } | ||
| 725 | - | ||
| 726 | - | ||
| 727 | - if(this.isEmpty(this.channel)){ | ||
| 728 | - this.$message.error('请选择通道'); | ||
| 729 | - return; | ||
| 730 | - } | ||
| 731 | - | ||
| 732 | - if(this.isEmpty(this.startTime)){ | ||
| 733 | - this.$message.error('请选择开始时间'); | ||
| 734 | - return; | ||
| 735 | - } | ||
| 736 | - | ||
| 737 | - if(this.isEmpty(this.endTime)){ | ||
| 738 | - this.$message.error('请选择结束时间'); | ||
| 739 | - return; | ||
| 740 | - } | ||
| 741 | - | ||
| 742 | - this.showLoading(); | ||
| 743 | - | ||
| 744 | - let pageObj = this; | ||
| 745 | - this.$axios({ | ||
| 746 | - method: 'get', | ||
| 747 | - url: '/api/jt1078/query/history/list/' + this.sim + '/' + this.channel+"/"+this.startTime+"/"+this.endTime | ||
| 748 | - }).then(function (res) { | ||
| 749 | - | ||
| 750 | - | ||
| 751 | - if(res &&res.data && res.data.data && res.data.data.obj && res.data.data.code==1 && res.data.data.obj.data && res.data.data.obj.data.items){ | ||
| 752 | - let length = res.data.data.obj.data.items.length; | ||
| 753 | - let html = "<div class='historyListDiv'><ul>"; | ||
| 754 | - for (let i = 0; i < length; i++) { | ||
| 755 | - let item = res.data.data.obj.data.items[i]; | ||
| 756 | - if(item.channelNo === pageObj.channel){ | ||
| 757 | - let title = item.startTime+"——"+item.endTime; | ||
| 758 | - html+="<li class='historyListLi' click='playHistoryItem()' startTime = '"+item.startTime+"' endTime='"+item.endTime+"' streamType='"+item.streamType+"' title='"+title+"' channelMapping='"+item.channelMapping+"'>"+title+"</li>"; | ||
| 759 | - } | ||
| 760 | - } | ||
| 761 | - pageObj.historyPlayListHtml = html+"</ul></div>"; | ||
| 762 | - pageObj.closeLoading(); | ||
| 763 | - }else if(res && res.data && res.data.data && res.data.data.msg){ | ||
| 764 | - pageObj.$message.error(res.data.data.msg); | ||
| 765 | - pageObj.closeLoading(); | ||
| 766 | - }else{ | ||
| 767 | - pageObj.closeLoading(); | ||
| 768 | - } | ||
| 769 | - }); | ||
| 770 | - }, | ||
| 771 | - playHistoryItem(e){ | ||
| 772 | - if(this.isEmpty(this.carTreeNode)){ | ||
| 773 | - this.$message.error('请选择车辆'); | ||
| 774 | - return; | ||
| 775 | - } | ||
| 776 | - if(this.isEmpty(this.sim)){ | ||
| 777 | - this.$message.error('无法获取SIM卡信息,请检查设备'); | ||
| 778 | - return; | ||
| 779 | - } | ||
| 780 | - | ||
| 781 | - | ||
| 782 | - if(this.isEmpty(this.channel)){ | ||
| 783 | - this.$message.error('请选择通道'); | ||
| 784 | - return; | ||
| 785 | - } | ||
| 786 | - | ||
| 787 | - if(this.isEmpty(this.startTime)){ | ||
| 788 | - this.$message.error('请选择开始时间'); | ||
| 789 | - return; | ||
| 790 | - } | ||
| 791 | - | ||
| 792 | - if(this.isEmpty(this.endTime)){ | ||
| 793 | - this.$message.error('请选择结束时间'); | ||
| 794 | - return; | ||
| 795 | - } | ||
| 796 | - | ||
| 797 | - let pageObj = this; | ||
| 798 | - | ||
| 799 | - | ||
| 800 | - this.videoUrl =[]; | ||
| 801 | - | ||
| 802 | - | ||
| 803 | - pageObj.$axios({ | ||
| 804 | - method: 'get', | ||
| 805 | - url: '/api/jt1078/query/send/request/io/history/' + pageObj.sim + '/' + pageObj.channel+"/"+e.target.getAttribute('startTime')+"/"+e.target.getAttribute('endTime')+"/"+e.target.getAttribute('channelMapping') | ||
| 806 | - }).then(function (res) { | ||
| 807 | - | ||
| 808 | - | ||
| 809 | - if (res.data && res.data.data && res.data.data.data) { | ||
| 810 | - let videoUrl1; | ||
| 811 | - if (location.protocol === "https:") { | ||
| 812 | - videoUrl1 = res.data.data.data.wss_flv; | ||
| 813 | - } else { | ||
| 814 | - videoUrl1 = res.data.data.data.ws_flv; | ||
| 815 | - } | ||
| 816 | - pageObj.downloadURL = res.data.data.data.flv; | ||
| 817 | - pageObj.port=res.data.data.port; | ||
| 818 | - pageObj.httpPort = res.data.data.httpPort; | ||
| 819 | - pageObj.stream = res.data.data.stream; | ||
| 820 | - pageObj.videoUrlHistory = videoUrl1; | ||
| 821 | - | ||
| 822 | - let itemData = new Object(); | ||
| 823 | - itemData.deviceId = pageObj.sim; | ||
| 824 | - // this.isLoging = true; | ||
| 825 | - itemData.channelId= pageObj.channel; | ||
| 826 | - itemData.playUrl = videoUrl1; | ||
| 827 | - console.log(pageObj.playerIdx); | ||
| 828 | - | ||
| 829 | - pageObj.setPlayUrl(videoUrl1, 0); | ||
| 830 | - pageObj.hisotoryPlayFlag = true; | ||
| 831 | - // pageObj.$nextTick(() => { | ||
| 832 | - // pageObj.createdPlay(); | ||
| 833 | - // pageObj.closeLoading(); | ||
| 834 | - // }) | ||
| 835 | - } else if(res.data.data && res.data.data.msg){ | ||
| 836 | - pageObj.$message.error(res.data.data.msg); | ||
| 837 | - } else if(res.data.msg){ | ||
| 838 | - pageObj.$message.error(res.data.msg); | ||
| 839 | - }else if(res.msg){ | ||
| 840 | - pageObj.$message.error(res.msg); | ||
| 841 | - } | ||
| 842 | - pageObj.closeLoading(); | ||
| 843 | - }); | ||
| 844 | - | ||
| 845 | - }, | 1157 | + /** |
| 1158 | + * 视频一键播放 | ||
| 1159 | + */ | ||
| 846 | oneClickPlayback() { | 1160 | oneClickPlayback() { |
| 847 | - if (this.isEmpty(this.carTreeNode)) { | 1161 | + if (this.isEmpty(this.simNodeData)) { |
| 848 | this.$message.error('请选择车辆'); | 1162 | this.$message.error('请选择车辆'); |
| 849 | return; | 1163 | return; |
| 850 | } | 1164 | } |
| 851 | - if (this.isEmpty(this.carTreeNode.abnormalStatus)) { | 1165 | + if (this.isEmpty(this.simNodeData.abnormalStatus)) { |
| 852 | this.$message.error('请检查车辆状态'); | 1166 | this.$message.error('请检查车辆状态'); |
| 853 | return; | 1167 | return; |
| 854 | } | 1168 | } |
| 855 | - if (this.carTreeNode.abnormalStatus != 1) { | 1169 | + if (this.simNodeData.abnormalStatus != 1) { |
| 856 | this.$message.error('车辆设备离线,请检查设备'); | 1170 | this.$message.error('车辆设备离线,请检查设备'); |
| 857 | return; | 1171 | return; |
| 858 | } | 1172 | } |
| 859 | - if (this.isEmpty(this.sim)) { | 1173 | + if (this.isEmpty(this.simNodeData.sim)) { |
| 860 | this.$message.error('无法获取SIM卡信息,请检查设备'); | 1174 | this.$message.error('无法获取SIM卡信息,请检查设备'); |
| 861 | return; | 1175 | return; |
| 862 | } | 1176 | } |
| 863 | - this.spilt = 12; | ||
| 864 | - this.playOneAllChannel(0); | 1177 | + this.spilt = 9; |
| 1178 | + let data = Array.from({length: this.spilt}, (_, i) => `${this.simNodeData.sim}-${i + 1}`); | ||
| 1179 | + this.beachSendIORequest(data); | ||
| 865 | }, | 1180 | }, |
| 866 | - playOneAllChannel(channel) { | ||
| 867 | - if (channel == 9) { | ||
| 868 | - return; | ||
| 869 | - } | ||
| 870 | - let item = new Object(); | ||
| 871 | - item.deviceId = this.sim; | ||
| 872 | - item.channelId = 1 + channel; | ||
| 873 | - this.playerIdx = channel; | ||
| 874 | - let that = this; | ||
| 875 | - this.sendDevicePush(item, function () { | ||
| 876 | - that.playOneAllChannel(1 + channel); | ||
| 877 | - }); | 1181 | + /** |
| 1182 | + * 批量发送推流请求 | ||
| 1183 | + * @param data | ||
| 1184 | + */ | ||
| 1185 | + beachSendIORequest(data) { | ||
| 1186 | + console.log(data) | ||
| 1187 | + this.$axios({ | ||
| 1188 | + method: 'post', | ||
| 1189 | + url: '/api/jt1078/query/beachSend/request/io', | ||
| 1190 | + data: data, | ||
| 1191 | + headers: { | ||
| 1192 | + 'Content-Type': 'application/json', // 设置请求头 | ||
| 1193 | + } | ||
| 1194 | + }).then( | ||
| 1195 | + res => { | ||
| 1196 | + let dataList = res.data.data; | ||
| 1197 | + console.log(dataList); | ||
| 1198 | + if (res.data.code == 0 && dataList != null && dataList.length >= 0) { | ||
| 1199 | + for (let i in dataList) { | ||
| 1200 | + this.setPlayUrl(dataList[i].ws_flv, i); | ||
| 1201 | + } | ||
| 1202 | + } else { | ||
| 1203 | + this.$message.error(res.data.msg); | ||
| 1204 | + } | ||
| 1205 | + } | ||
| 1206 | + ) | ||
| 878 | }, | 1207 | }, |
| 1208 | + // playOneAllChannel(channel) { | ||
| 1209 | + // if (channel == 9) { | ||
| 1210 | + // return; | ||
| 1211 | + // } | ||
| 1212 | + // let item = new Object(); | ||
| 1213 | + // item.deviceId = this.sim; | ||
| 1214 | + // item.channelId = 1 + channel; | ||
| 1215 | + // this.playerIdx = channel; | ||
| 1216 | + // | ||
| 1217 | + // this.sendDevicePush(item); | ||
| 1218 | + // }, | ||
| 879 | spiltClickFun(val) { | 1219 | spiltClickFun(val) { |
| 880 | this.spilt = val; | 1220 | this.spilt = val; |
| 881 | if (val - 1 < this.playerIdx) { | 1221 | if (val - 1 < this.playerIdx) { |
| 882 | this.playerIdx = val - 1; | 1222 | this.playerIdx = val - 1; |
| 883 | } | 1223 | } |
| 884 | }, | 1224 | }, |
| 885 | - downloadFunction(){ | ||
| 886 | - console.log(this.downloadURL); | ||
| 887 | - | ||
| 888 | - if(this.isEmpty(this.downloadURL)){ | ||
| 889 | - return; | ||
| 890 | - } | ||
| 891 | - | ||
| 892 | - window.open(this.downloadURL,"_download"); | ||
| 893 | - }, | ||
| 894 | - | ||
| 895 | closeSelectItem() { | 1225 | closeSelectItem() { |
| 896 | console.log("============================>" + this.playerIdx); | 1226 | console.log("============================>" + this.playerIdx); |
| 897 | this.setPlayUrl(null, this.playerIdx) | 1227 | this.setPlayUrl(null, this.playerIdx) |
| 898 | - // this.videoUrl[this.playerIdx]=null; | ||
| 899 | - // this.sendIORequestStop1(this.sim,this.playerIdx+1); | ||
| 900 | }, | 1228 | }, |
| 901 | closeSelectCarItem() { | 1229 | closeSelectCarItem() { |
| 902 | for (let index = 0; index < 9; index++) { | 1230 | for (let index = 0; index < 9; index++) { |
| 903 | this.setPlayUrl(null, index) | 1231 | this.setPlayUrl(null, index) |
| 904 | - // this.videoUrl[this.playerIdx]=null; | ||
| 905 | - this.sendIORequestStop1(this.sim, index + 1); | ||
| 906 | - } | ||
| 907 | - }, | ||
| 908 | - treeRightMenuFun(event, treeId, treeNode) { | ||
| 909 | - if (treeNode.type == '301' || treeNode.type == 301) { | ||
| 910 | - this.rightMenuId = "carRMenu"; | ||
| 911 | - this.showRMenu(event); | ||
| 912 | - this.carTreeNode = treeNode; | ||
| 913 | - this.sim = treeNode.sim; | ||
| 914 | - this.channel = null; | ||
| 915 | - } else if (treeNode.type == '401' || treeNode.type == 401) { | ||
| 916 | - this.rightMenuId = "channelCarRMenu"; | ||
| 917 | - this.showRMenu(event); | ||
| 918 | - this.channel = treeNode.id; | ||
| 919 | - } else { | ||
| 920 | - this.carTreeNode = null; | ||
| 921 | - this.sim = null; | ||
| 922 | - this.channel = null; | ||
| 923 | - hidden(); | ||
| 924 | } | 1232 | } |
| 925 | }, | 1233 | }, |
| 926 | showRMenu(event) { | 1234 | showRMenu(event) { |
| @@ -947,14 +1255,26 @@ export default { | @@ -947,14 +1255,26 @@ export default { | ||
| 947 | } | 1255 | } |
| 948 | }; | 1256 | }; |
| 949 | </script> | 1257 | </script> |
| 950 | -<style> | 1258 | +<style scoped> |
| 1259 | +.inspections-tree >>> .el-tree { | ||
| 1260 | + padding-bottom: 22px; | ||
| 1261 | +} | ||
| 1262 | + | ||
| 1263 | +.device-list-tree >>> .el-tree { | ||
| 1264 | + padding-bottom: 13px; | ||
| 1265 | +} | ||
| 1266 | + | ||
| 1267 | +.device-list-tree >>> .el-tree-node__content { | ||
| 1268 | + padding-bottom: 13px; | ||
| 1269 | + height: 20px; | ||
| 1270 | +} | ||
| 1271 | + | ||
| 951 | .device-tree-main-box { | 1272 | .device-tree-main-box { |
| 952 | text-align: left; | 1273 | text-align: left; |
| 953 | } | 1274 | } |
| 954 | 1275 | ||
| 955 | .btn { | 1276 | .btn { |
| 956 | margin: 0 10px; | 1277 | margin: 0 10px; |
| 957 | - | ||
| 958 | } | 1278 | } |
| 959 | 1279 | ||
| 960 | .btn:hover { | 1280 | .btn:hover { |
| @@ -963,7 +1283,6 @@ export default { | @@ -963,7 +1283,6 @@ export default { | ||
| 963 | 1283 | ||
| 964 | .btn.active { | 1284 | .btn.active { |
| 965 | color: #409EFF; | 1285 | color: #409EFF; |
| 966 | - | ||
| 967 | } | 1286 | } |
| 968 | 1287 | ||
| 969 | .redborder { | 1288 | .redborder { |
| @@ -995,7 +1314,6 @@ export default { | @@ -995,7 +1314,6 @@ export default { | ||
| 995 | overflow-x: hidden; | 1314 | overflow-x: hidden; |
| 996 | } | 1315 | } |
| 997 | 1316 | ||
| 998 | - | ||
| 999 | /* 菜单的样式 */ | 1317 | /* 菜单的样式 */ |
| 1000 | .rMenu { | 1318 | .rMenu { |
| 1001 | position: absolute; | 1319 | position: absolute; |
| @@ -1026,8 +1344,7 @@ export default { | @@ -1026,8 +1344,7 @@ export default { | ||
| 1026 | li#menu-item-delete, li#menu-item-rename { | 1344 | li#menu-item-delete, li#menu-item-rename { |
| 1027 | margin-top: 1px; | 1345 | margin-top: 1px; |
| 1028 | } | 1346 | } |
| 1029 | -</style> | ||
| 1030 | -<style> | 1347 | + |
| 1031 | .videoList { | 1348 | .videoList { |
| 1032 | display: flex; | 1349 | display: flex; |
| 1033 | flex-wrap: wrap; | 1350 | flex-wrap: wrap; |
| @@ -1106,6 +1423,7 @@ li#menu-item-delete, li#menu-item-rename { | @@ -1106,6 +1423,7 @@ li#menu-item-delete, li#menu-item-rename { | ||
| 1106 | overflow-y: auto; /* 内容超出时显示垂直滚动条 */ | 1423 | overflow-y: auto; /* 内容超出时显示垂直滚动条 */ |
| 1107 | overflow-x: hidden; /* 隐藏水平滚动条 */ | 1424 | overflow-x: hidden; /* 隐藏水平滚动条 */ |
| 1108 | } | 1425 | } |
| 1426 | + | ||
| 1109 | .transfer-footer { | 1427 | .transfer-footer { |
| 1110 | margin-left: 20px; | 1428 | margin-left: 20px; |
| 1111 | padding: 6px 5px; | 1429 | padding: 6px 5px; |
web_src/src/components/FlowStatistics.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div style="width: 2000px;"> | ||
| 3 | + <el-container v-loading="loading" style="height: 100%;width: 100%" element-loading-text="拼命加载中"> | ||
| 4 | + <div style="width:100%;display: flex;flex-direction: column;justify-content: space-between;"> | ||
| 5 | + <div class="block" style="width: 100%;text-align:left;margin-bottom:15px;"> | ||
| 6 | + <el-card class="box-card" style="width: 100%"> | ||
| 7 | + <el-form> | ||
| 8 | + <el-col :span="4"> | ||
| 9 | + <el-form-item label="时间类型"> | ||
| 10 | + <el-select v-model="timeType" placeholder="请选择时间类型"> | ||
| 11 | + <el-option | ||
| 12 | + v-for="item in timeList" | ||
| 13 | + :key="item.value" | ||
| 14 | + :label="item.label" | ||
| 15 | + :value="item.value" | ||
| 16 | + @change="getDatesByTimeFrame"> | ||
| 17 | + </el-option> | ||
| 18 | + </el-select> | ||
| 19 | + </el-form-item> | ||
| 20 | + </el-col> | ||
| 21 | + <el-col :span="4"> | ||
| 22 | + <el-form-item label="日期"> | ||
| 23 | + <el-date-picker | ||
| 24 | + v-model="time" | ||
| 25 | + align="right" | ||
| 26 | + type="date" | ||
| 27 | + placeholder="选择日期" | ||
| 28 | + :picker-options="pickerOptions" v-if="timeType === 'day'"/> | ||
| 29 | + <el-date-picker | ||
| 30 | + v-model="time" | ||
| 31 | + value-format="yyyy-M" | ||
| 32 | + type="month" | ||
| 33 | + placeholder="选择月" v-if="timeType === 'month'"/> | ||
| 34 | + <el-date-picker | ||
| 35 | + v-model="time" | ||
| 36 | + type="year" | ||
| 37 | + placeholder="选择年" v-if="timeType === 'year'"/> | ||
| 38 | + </el-form-item> | ||
| 39 | + </el-col> | ||
| 40 | + <el-col :span="4" v-if="statisticsType !== 'All'"> | ||
| 41 | + <el-form-item label="车辆"> | ||
| 42 | + <car-tree-one v-model="sim_channel"/> | ||
| 43 | + </el-form-item> | ||
| 44 | + </el-col> | ||
| 45 | + <el-col :span="5"> | ||
| 46 | + <el-form-item label="统计类型"> | ||
| 47 | + <el-select v-model="statisticsType" placeholder="请选择统计类型" @change="searchFlowList"> | ||
| 48 | + <el-option | ||
| 49 | + v-for="item in statisticsList" | ||
| 50 | + :key="item.value" | ||
| 51 | + :label="item.label" | ||
| 52 | + :value="item.value" | ||
| 53 | + > | ||
| 54 | + </el-option> | ||
| 55 | + </el-select> | ||
| 56 | + </el-form-item> | ||
| 57 | + </el-col> | ||
| 58 | + <el-col :span="3"> | ||
| 59 | + <el-form-item> | ||
| 60 | + <el-button @click="searchFlowList()">搜索</el-button> | ||
| 61 | + </el-form-item> | ||
| 62 | + </el-col> | ||
| 63 | + </el-form> | ||
| 64 | + </el-card> | ||
| 65 | + </div> | ||
| 66 | + <div style="width: 100%;display:flex;flex-direction:row; justify-content:space-between;"> | ||
| 67 | + <el-card class="box-card" style="width: 100%;height: 80vh"> | ||
| 68 | + <el-table | ||
| 69 | + :data="tableData" | ||
| 70 | + height="250" | ||
| 71 | + border | ||
| 72 | + style="width: 100%;height: 75vh;"> | ||
| 73 | + <el-table-column | ||
| 74 | + prop="time" | ||
| 75 | + label="日期" | ||
| 76 | + > | ||
| 77 | + </el-table-column> | ||
| 78 | + <el-table-column | ||
| 79 | + label="车辆自编号" v-if="statisticsType !== 'All'"> | ||
| 80 | + <template slot-scope="scope"> | ||
| 81 | + <span>{{ `${scope.row.carData.nbbm} ` }}</span> | ||
| 82 | + <el-button type="text" @click="clickInformation(scope.row)">[详细信息]</el-button> | ||
| 83 | + </template> | ||
| 84 | + </el-table-column> | ||
| 85 | + <el-table-column | ||
| 86 | + prop="channel" | ||
| 87 | + label="通道号" | ||
| 88 | + v-if="statisticsType === 'channel'"> | ||
| 89 | + </el-table-column> | ||
| 90 | + <el-table-column | ||
| 91 | + prop="count" | ||
| 92 | + label="统计车辆数" | ||
| 93 | + v-if="statisticsType === 'All'"> | ||
| 94 | + </el-table-column> | ||
| 95 | + <el-table-column | ||
| 96 | + prop="flow" | ||
| 97 | + label="流量"> | ||
| 98 | + <template slot-scope="scope"> | ||
| 99 | + {{ formattedBytes(scope.row.flow) }} | ||
| 100 | + </template> | ||
| 101 | + </el-table-column> | ||
| 102 | + </el-table> | ||
| 103 | + </el-card> | ||
| 104 | + </div> | ||
| 105 | + </div> | ||
| 106 | + <el-dialog | ||
| 107 | + :title="`${information.nbbm}车辆详细信息`" | ||
| 108 | + :visible.sync="open" | ||
| 109 | + width="30%" | ||
| 110 | + :before-close="handleClose"> | ||
| 111 | + <el-descriptions class="margin-top" :column="1" border> | ||
| 112 | + <el-descriptions-item> | ||
| 113 | + <template slot="label"> | ||
| 114 | + 车辆自编号 | ||
| 115 | + </template> | ||
| 116 | + {{ information.nbbm }} | ||
| 117 | + </el-descriptions-item> | ||
| 118 | + <el-descriptions-item> | ||
| 119 | + <template slot="label"> | ||
| 120 | + sim卡号 | ||
| 121 | + </template> | ||
| 122 | + {{ information.sim }} | ||
| 123 | + </el-descriptions-item> | ||
| 124 | + <el-descriptions-item v-if="information.lineName"> | ||
| 125 | + <template slot="label"> | ||
| 126 | + 线路名称 | ||
| 127 | + </template> | ||
| 128 | + {{ information.lineName }} | ||
| 129 | + </el-descriptions-item> | ||
| 130 | + <el-descriptions-item v-if="information.carPlate"> | ||
| 131 | + <template slot="label"> | ||
| 132 | + <i class="el-icon-tickets"></i> | ||
| 133 | + 车牌号 | ||
| 134 | + </template> | ||
| 135 | + {{ information.carPlate }} | ||
| 136 | + </el-descriptions-item> | ||
| 137 | + </el-descriptions> | ||
| 138 | + <span slot="footer" class="dialog-footer"> | ||
| 139 | + <el-button @click="closeInformation">关闭</el-button> | ||
| 140 | + </span> | ||
| 141 | + </el-dialog> | ||
| 142 | + </el-container> | ||
| 143 | + </div> | ||
| 144 | +</template> | ||
| 145 | + | ||
| 146 | +<script> | ||
| 147 | +//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等), | ||
| 148 | +//例如:import 《组件名称》 from '《组件路径》, | ||
| 149 | +import player from "./common/jessibuca.vue"; | ||
| 150 | +import CarTree from "./JT1078Components/cascader/CarTree.vue"; | ||
| 151 | +import HistoricalData from "./JT1078Components/historical/HistoricalDataTree.vue"; | ||
| 152 | +import {parseTime} from "../../utils/ruoyi"; | ||
| 153 | +import CarTreeOne from "./JT1078Components/cascader/CarTreeOne.vue"; | ||
| 154 | + | ||
| 155 | +export default { | ||
| 156 | + //import引入的组件需要注入到对象中才能使用" | ||
| 157 | + components: {CarTreeOne, HistoricalData, CarTree, player}, | ||
| 158 | + props: {}, | ||
| 159 | + data() { | ||
| 160 | + //这里存放数据" | ||
| 161 | + return { | ||
| 162 | + open: false, | ||
| 163 | + information: {}, | ||
| 164 | + tableData: [], | ||
| 165 | + historyData: [], | ||
| 166 | + //遮罩层 | ||
| 167 | + loading: false, | ||
| 168 | + //sim号和通道号,格式为:sim-channel | ||
| 169 | + sim_channel: null, | ||
| 170 | + //选择时间 | ||
| 171 | + time: '', | ||
| 172 | + //时间类型 | ||
| 173 | + timeType: 'day', | ||
| 174 | + //统计类型 | ||
| 175 | + statisticsType: 'sim', | ||
| 176 | + //时间选择下拉框 | ||
| 177 | + timeList: [ | ||
| 178 | + {value: 'day', label: '按天统计'}, | ||
| 179 | + {value: 'month', label: '按月统计'}, | ||
| 180 | + {value: 'year', label: '按年统计'}, | ||
| 181 | + ], | ||
| 182 | + //统计类型 | ||
| 183 | + statisticsList: [ | ||
| 184 | + {value: 'sim', label: '按车辆统计'}, | ||
| 185 | + {value: 'channel', label: '按通道统计'}, | ||
| 186 | + {value: 'All', label: '全量统计'}, | ||
| 187 | + ], | ||
| 188 | + //日期快捷选择 | ||
| 189 | + pickerOptions: { | ||
| 190 | + disabledDate(time) { | ||
| 191 | + return time.getTime() > Date.now(); | ||
| 192 | + }, | ||
| 193 | + shortcuts: [{ | ||
| 194 | + text: '今天', | ||
| 195 | + onClick(picker) { | ||
| 196 | + picker.$emit('pick', new Date()); | ||
| 197 | + } | ||
| 198 | + }, { | ||
| 199 | + text: '昨天', | ||
| 200 | + onClick(picker) { | ||
| 201 | + const date = new Date(); | ||
| 202 | + date.setTime(date.getTime() - 3600 * 1000 * 24); | ||
| 203 | + picker.$emit('pick', date); | ||
| 204 | + } | ||
| 205 | + }, { | ||
| 206 | + text: '一周前', | ||
| 207 | + onClick(picker) { | ||
| 208 | + const date = new Date(); | ||
| 209 | + date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); | ||
| 210 | + picker.$emit('pick', date); | ||
| 211 | + } | ||
| 212 | + }] | ||
| 213 | + }, | ||
| 214 | + }; | ||
| 215 | + }, | ||
| 216 | + //计算属性 类似于data概念", | ||
| 217 | + computed: {}, | ||
| 218 | + //监控data中的数据变化", | ||
| 219 | + watch: { | ||
| 220 | + timeType() { | ||
| 221 | + this.getDatesByTimeFrame() | ||
| 222 | + } | ||
| 223 | + }, | ||
| 224 | + //方法集合", | ||
| 225 | + methods: { | ||
| 226 | + /** | ||
| 227 | + * 搜索流量统计数据 | ||
| 228 | + */ | ||
| 229 | + searchFlowList() { | ||
| 230 | + this.loading = true | ||
| 231 | + let simChannel = null; | ||
| 232 | + console.log(this.sim_channel); | ||
| 233 | + if (this.sim_channel) { | ||
| 234 | + simChannel = this.sim_channel[this.sim_channel.length - 1]; | ||
| 235 | + } | ||
| 236 | + this.$axios({ | ||
| 237 | + method: "GET", | ||
| 238 | + url: "/flow/list/" + this.timeType + "/" + this.statisticsType + "/" + this.time + "/" + simChannel, | ||
| 239 | + }).then(res => { | ||
| 240 | + this.tableData = res.data.data | ||
| 241 | + this.loading = false | ||
| 242 | + }) | ||
| 243 | + }, | ||
| 244 | + destroy(idx) { | ||
| 245 | + console.log(idx); | ||
| 246 | + this.clear(idx.substring(idx.length - 1)) | ||
| 247 | + }, | ||
| 248 | + /** | ||
| 249 | + * 获取时间 | ||
| 250 | + */ | ||
| 251 | + getDatesByTimeFrame() { | ||
| 252 | + const today = new Date(); | ||
| 253 | + switch (this.timeType.toLowerCase()) { | ||
| 254 | + case 'day': | ||
| 255 | + this.time = parseTime(today, '{y}-{m}-{d} {h}:{i}:{s}'); | ||
| 256 | + break; | ||
| 257 | + | ||
| 258 | + case 'month': | ||
| 259 | + let time = parseTime(today, '{y}-{m}'); | ||
| 260 | + let split = time.split('-'); | ||
| 261 | + this.time = split[1].substring(0, 1) === '0' ? split[0] + '-' + split[1].substring(1, 2) : time; | ||
| 262 | + break; | ||
| 263 | + | ||
| 264 | + case 'year': | ||
| 265 | + this.time = parseTime(today, '{y}'); | ||
| 266 | + break; | ||
| 267 | + default: | ||
| 268 | + console.log('Invalid time frame provided.'); | ||
| 269 | + } | ||
| 270 | + this.searchFlowList() | ||
| 271 | + }, | ||
| 272 | + /** | ||
| 273 | + * 流量换算 | ||
| 274 | + */ | ||
| 275 | + formattedBytes(value) { | ||
| 276 | + if (value >= 1024 * 1024 * 1024) { // GB | ||
| 277 | + return `${(value / (1024 * 1024 * 1024)).toFixed(2)} GB`; | ||
| 278 | + } else if (value >= 1024 * 1024) { // MB | ||
| 279 | + return `${(value / (1024 * 1024)).toFixed(2)} MB`; | ||
| 280 | + } else if (value >= 1024) { // KB | ||
| 281 | + return `${(value / 1024).toFixed(2)} KB`; | ||
| 282 | + } else { // Bytes | ||
| 283 | + return `${value} Bytes`; | ||
| 284 | + } | ||
| 285 | + }, | ||
| 286 | + handleClose(done) { | ||
| 287 | + this.$confirm('确认关闭?') | ||
| 288 | + .then(_ => { | ||
| 289 | + done(); | ||
| 290 | + }) | ||
| 291 | + .catch(_ => { | ||
| 292 | + }); | ||
| 293 | + }, | ||
| 294 | + /** | ||
| 295 | + * 详细信息按钮 | ||
| 296 | + */ | ||
| 297 | + clickInformation(val) { | ||
| 298 | + if (val) { | ||
| 299 | + this.open = true; | ||
| 300 | + this.information = val.carData | ||
| 301 | + } else { | ||
| 302 | + this.$message.error("车辆信息有误") | ||
| 303 | + } | ||
| 304 | + }, | ||
| 305 | + /** | ||
| 306 | + * 关闭框 | ||
| 307 | + */ | ||
| 308 | + closeInformation() { | ||
| 309 | + this.open = false; | ||
| 310 | + this.information = {}; | ||
| 311 | + } | ||
| 312 | + }, | ||
| 313 | + //生命周期 - 创建完成(可以访问当前this实例)", | ||
| 314 | + created() { | ||
| 315 | + this.getDatesByTimeFrame() | ||
| 316 | + this.searchFlowList(); | ||
| 317 | + }, | ||
| 318 | + //生命周期 - 挂载完成(可以访问DOM元素)", | ||
| 319 | + mounted() { | ||
| 320 | + }, | ||
| 321 | + beforeCreate() { | ||
| 322 | + }, //生命周期 - 创建之前", | ||
| 323 | + beforeMount() { | ||
| 324 | + }, //生命周期 - 挂载之前", | ||
| 325 | + beforeUpdate() { | ||
| 326 | + }, //生命周期 - 更新之前", | ||
| 327 | + updated() { | ||
| 328 | + }, //生命周期 - 更新之后", | ||
| 329 | + beforeDestroy() { | ||
| 330 | + }, //生命周期 - 销毁之前", | ||
| 331 | + destroyed() { | ||
| 332 | + }, //生命周期 - 销毁完成", | ||
| 333 | + activated() { | ||
| 334 | + } //如果页面有keep-alive缓存功能,这个函数会触发", | ||
| 335 | +}; | ||
| 336 | +</script> | ||
| 337 | +<style scoped> | ||
| 338 | +.device-tree-main-box { | ||
| 339 | + text-align: left; | ||
| 340 | +} | ||
| 341 | + | ||
| 342 | +.btn { | ||
| 343 | + margin: 0 10px; | ||
| 344 | + | ||
| 345 | +} | ||
| 346 | + | ||
| 347 | +.btn:hover { | ||
| 348 | + color: #409EFF; | ||
| 349 | +} | ||
| 350 | + | ||
| 351 | +.btn.active { | ||
| 352 | + color: #409EFF; | ||
| 353 | + | ||
| 354 | +} | ||
| 355 | + | ||
| 356 | +.redborder { | ||
| 357 | + border: 2px solid red !important; | ||
| 358 | +} | ||
| 359 | + | ||
| 360 | +.play-box { | ||
| 361 | + background-color: #000000; | ||
| 362 | + border: 2px solid #505050; | ||
| 363 | + display: flex; | ||
| 364 | + align-items: center; | ||
| 365 | + justify-content: center; | ||
| 366 | +} | ||
| 367 | + | ||
| 368 | +.historyListLi { | ||
| 369 | + width: 97%; | ||
| 370 | + white-space: nowrap; | ||
| 371 | + text-overflow: ellipsis; | ||
| 372 | + cursor: pointer; | ||
| 373 | + padding: 3px; | ||
| 374 | + margin-bottom: 6px; | ||
| 375 | + border: 1px solid #000000; | ||
| 376 | +} | ||
| 377 | + | ||
| 378 | +.historyListDiv { | ||
| 379 | + height: 80vh; | ||
| 380 | + width: 100%; | ||
| 381 | + overflow-y: auto; | ||
| 382 | + overflow-x: hidden; | ||
| 383 | +} | ||
| 384 | + | ||
| 385 | + | ||
| 386 | +/* 菜单的样式 */ | ||
| 387 | +.rMenu { | ||
| 388 | + position: absolute; | ||
| 389 | + top: 0; | ||
| 390 | + display: none; | ||
| 391 | + margin: 0; | ||
| 392 | + padding: 0; | ||
| 393 | + text-align: left; | ||
| 394 | + border: 1px solid #BFBFBF; | ||
| 395 | + border-radius: 3px; | ||
| 396 | + background-color: #EEE; | ||
| 397 | + box-shadow: 0 0 10px #AAA; | ||
| 398 | +} | ||
| 399 | + | ||
| 400 | +.rMenu li { | ||
| 401 | + width: 170px; | ||
| 402 | + list-style: none outside none; | ||
| 403 | + cursor: default; | ||
| 404 | + color: #666; | ||
| 405 | + margin-left: -20px; | ||
| 406 | +} | ||
| 407 | + | ||
| 408 | +.rMenu li:hover { | ||
| 409 | + color: #EEE; | ||
| 410 | + background-color: #666; | ||
| 411 | +} | ||
| 412 | + | ||
| 413 | +li#menu-item-delete, li#menu-item-rename { | ||
| 414 | + margin-top: 1px; | ||
| 415 | +} | ||
| 416 | +</style> | ||
| 417 | +<style> | ||
| 418 | +.videoList { | ||
| 419 | + display: flex; | ||
| 420 | + flex-wrap: wrap; | ||
| 421 | + align-content: flex-start; | ||
| 422 | +} | ||
| 423 | + | ||
| 424 | +.video-item { | ||
| 425 | + position: relative; | ||
| 426 | + width: 15rem; | ||
| 427 | + height: 10rem; | ||
| 428 | + margin-right: 1rem; | ||
| 429 | + background-color: #000000; | ||
| 430 | +} | ||
| 431 | + | ||
| 432 | +.video-item-img { | ||
| 433 | + position: absolute; | ||
| 434 | + top: 0; | ||
| 435 | + bottom: 0; | ||
| 436 | + left: 0; | ||
| 437 | + right: 0; | ||
| 438 | + margin: auto; | ||
| 439 | + width: 100%; | ||
| 440 | + height: 100%; | ||
| 441 | +} | ||
| 442 | + | ||
| 443 | +.video-item-img:after { | ||
| 444 | + content: ""; | ||
| 445 | + display: inline-block; | ||
| 446 | + position: absolute; | ||
| 447 | + z-index: 2; | ||
| 448 | + top: 0; | ||
| 449 | + bottom: 0; | ||
| 450 | + left: 0; | ||
| 451 | + right: 0; | ||
| 452 | + margin: auto; | ||
| 453 | + width: 3rem; | ||
| 454 | + height: 3rem; | ||
| 455 | + background-image: url("../assets/loading.png"); | ||
| 456 | + background-size: cover; | ||
| 457 | + background-color: #000000; | ||
| 458 | +} | ||
| 459 | + | ||
| 460 | +.video-item-title { | ||
| 461 | + position: absolute; | ||
| 462 | + bottom: 0; | ||
| 463 | + color: #000000; | ||
| 464 | + background-color: #ffffff; | ||
| 465 | + line-height: 1.5rem; | ||
| 466 | + padding: 0.3rem; | ||
| 467 | + width: 14.4rem; | ||
| 468 | +} | ||
| 469 | + | ||
| 470 | +.baidumap { | ||
| 471 | + width: 100%; | ||
| 472 | + height: 100%; | ||
| 473 | + border: none; | ||
| 474 | + position: absolute; | ||
| 475 | + left: 0; | ||
| 476 | + top: 0; | ||
| 477 | + right: 0; | ||
| 478 | + bottom: 0; | ||
| 479 | + margin: auto; | ||
| 480 | +} | ||
| 481 | + | ||
| 482 | +/* 去除百度地图版权那行字 和 百度logo */ | ||
| 483 | +.baidumap > .BMap_cpyCtrl { | ||
| 484 | + display: none !important; | ||
| 485 | +} | ||
| 486 | + | ||
| 487 | +.baidumap > .anchorBL { | ||
| 488 | + display: none !important; | ||
| 489 | +} | ||
| 490 | +</style> |
web_src/src/components/HistoricalRecord.vue
| @@ -4,7 +4,7 @@ | @@ -4,7 +4,7 @@ | ||
| 4 | <div style="width:100%;display: flex;flex-direction: column;justify-content: space-between;"> | 4 | <div style="width:100%;display: flex;flex-direction: column;justify-content: space-between;"> |
| 5 | <div class="block" style="width: 99%;text-align:left;margin-bottom:15px;"> | 5 | <div class="block" style="width: 99%;text-align:left;margin-bottom:15px;"> |
| 6 | <el-card class="box-card" style="width: 100%"> | 6 | <el-card class="box-card" style="width: 100%"> |
| 7 | - <car-tree v-model="sim_channel"/> | 7 | + <car-tree v-model="sim_channel" /> |
| 8 | <el-date-picker | 8 | <el-date-picker |
| 9 | v-model="date" | 9 | v-model="date" |
| 10 | align="right" | 10 | align="right" |
| @@ -26,14 +26,14 @@ | @@ -26,14 +26,14 @@ | ||
| 26 | </div> | 26 | </div> |
| 27 | 27 | ||
| 28 | <div style="width: 100%;display:flex;flex-direction:row; justify-content:space-between;"> | 28 | <div style="width: 100%;display:flex;flex-direction:row; justify-content:space-between;"> |
| 29 | - <div style="width:20%;height: 80vh" > | 29 | + <div style="width:22%;height: 80vh" > |
| 30 | <historical-data :history-data="historyData" @click="clickHistoricalPlay" /> | 30 | <historical-data :history-data="historyData" @click="clickHistoricalPlay" /> |
| 31 | </div> | 31 | </div> |
| 32 | - <div style="width: 78%;"> | 32 | + <div style="width: 77%;"> |
| 33 | <div style="width: 99%;height: 80vh;display: flex;flex-wrap: wrap;background-color: #000;"> | 33 | <div style="width: 99%;height: 80vh;display: flex;flex-wrap: wrap;background-color: #000;"> |
| 34 | - <div v-if="!videoUrl[0]" style="color: #ffffff;font-size: 30px;font-weight: bold;"></div> | ||
| 35 | - <player ref="player" v-else :videoUrl="videoUrl[0]" fluent autoplay @screenshot="shot" | ||
| 36 | - @destroy="destroy" style="width: 100%;height: 100%;"/> | 34 | + <div v-if="!videoUrl[0]" style="color: #ffffff;font-size: 30px;font-weight: bold;"></div> |
| 35 | + <player ref="player" v-else :videoUrl="videoUrl[0]" fluent autoplay @screenshot="shot" | ||
| 36 | + @destroy="destroy" style="width: 100%;height: 100%;"/> | ||
| 37 | </div> | 37 | </div> |
| 38 | </div> | 38 | </div> |
| 39 | </div> | 39 | </div> |
| @@ -109,10 +109,6 @@ export default { | @@ -109,10 +109,6 @@ export default { | ||
| 109 | clickHistoricalPlay(data) { | 109 | clickHistoricalPlay(data) { |
| 110 | this.playHistoryItem(data) | 110 | this.playHistoryItem(data) |
| 111 | }, | 111 | }, |
| 112 | - simChannelChange(val) { | ||
| 113 | - console.log(val); | ||
| 114 | - console.log(this.sim_channel) | ||
| 115 | - }, | ||
| 116 | /** | 112 | /** |
| 117 | * 下载历史视频 | 113 | * 下载历史视频 |
| 118 | */ | 114 | */ |
| @@ -135,6 +131,7 @@ export default { | @@ -135,6 +131,7 @@ export default { | ||
| 135 | return; | 131 | return; |
| 136 | } | 132 | } |
| 137 | let split = simChannel[simChannel.length - 1].split('-'); | 133 | let split = simChannel[simChannel.length - 1].split('-'); |
| 134 | + console.log("simChannel:",simChannel) | ||
| 138 | let sim = split[0]; | 135 | let sim = split[0]; |
| 139 | if (this.isEmpty(sim)) { | 136 | if (this.isEmpty(sim)) { |
| 140 | this.$message.error('无法获取SIM卡信息,请检查设备'); | 137 | this.$message.error('无法获取SIM卡信息,请检查设备'); |
| @@ -155,13 +152,16 @@ export default { | @@ -155,13 +152,16 @@ export default { | ||
| 155 | url: '/api/jt1078/query/history/list/' + sim + '/' + channel + "/" + this.startTime + "/" + this.endTime | 152 | url: '/api/jt1078/query/history/list/' + sim + '/' + channel + "/" + this.startTime + "/" + this.endTime |
| 156 | }).then( | 153 | }).then( |
| 157 | res=>{ | 154 | res=>{ |
| 155 | + console.log(res.data) | ||
| 158 | let items = res.data.data.obj.data.items; | 156 | let items = res.data.data.obj.data.items; |
| 159 | if (res && res.data && res.data.data && res.data.data.obj && res.data.data.code == 1 && res.data.data.obj.data && items) { | 157 | if (res && res.data && res.data.data && res.data.data.obj && res.data.data.code == 1 && res.data.data.obj.data && items) { |
| 160 | for (let i in items) { | 158 | for (let i in items) { |
| 161 | - items[i].sim = res.data.data.obj.data.clientId; | 159 | + items[i].sim = sim; |
| 160 | + items[i].channel = channel | ||
| 162 | items[i].name = items[i].startTime + '-' + items[i].endTime; | 161 | items[i].name = items[i].startTime + '-' + items[i].endTime; |
| 163 | } | 162 | } |
| 164 | this.historyData = items | 163 | this.historyData = items |
| 164 | + console.log(this.historyData) | ||
| 165 | this.loading = false | 165 | this.loading = false |
| 166 | } else if (res && res.data && res.data.data && res.data.data.msg) { | 166 | } else if (res && res.data && res.data.data && res.data.data.msg) { |
| 167 | this.$message.error(res.data.data.msg); | 167 | this.$message.error(res.data.data.msg); |
| @@ -169,7 +169,10 @@ export default { | @@ -169,7 +169,10 @@ export default { | ||
| 169 | } else { | 169 | } else { |
| 170 | this.loading = false | 170 | this.loading = false |
| 171 | } | 171 | } |
| 172 | - }); | 172 | + }).cache(res => { |
| 173 | + this.$message.error(res.msg); | ||
| 174 | + this.loading = false | ||
| 175 | + }) | ||
| 173 | }, | 176 | }, |
| 174 | /** | 177 | /** |
| 175 | * 时间转换 | 178 | * 时间转换 |
| @@ -213,7 +216,7 @@ export default { | @@ -213,7 +216,7 @@ export default { | ||
| 213 | this.videoUrl = []; | 216 | this.videoUrl = []; |
| 214 | this.$axios({ | 217 | this.$axios({ |
| 215 | method: 'get', | 218 | method: 'get', |
| 216 | - url: '/api/jt1078/query/send/request/io/history/' + e.sim + '/' + e.channelNo + "/" + e.startTime + "/" + e.endTime + "/" + e.channelMapping | 219 | + url: '/api/jt1078/query/send/request/io/history/' + e.sim + '/' + e.channel + "/" + e.startTime + "/" + e.endTime + "/" + e.channelMapping |
| 217 | }).then(res=> { | 220 | }).then(res=> { |
| 218 | if (res.data && res.data.data && res.data.data.data) { | 221 | if (res.data && res.data.data && res.data.data.data) { |
| 219 | let videoUrl1; | 222 | let videoUrl1; |
web_src/src/components/JT1078Components/cascader/CarTree.vue
| @@ -73,6 +73,7 @@ | @@ -73,6 +73,7 @@ | ||
| 73 | if (res.data.data.code == 1) { | 73 | if (res.data.data.code == 1) { |
| 74 | let data1 = res.data.data.result; | 74 | let data1 = res.data.data.result; |
| 75 | this.addChannel(data1); | 75 | this.addChannel(data1); |
| 76 | + console.log(data1) | ||
| 76 | } else if (res.data.data.message) { | 77 | } else if (res.data.data.message) { |
| 77 | this.$message.error(res.data.data.message); | 78 | this.$message.error(res.data.data.message); |
| 78 | } | 79 | } |
web_src/src/components/JT1078Components/cascader/CarTreeOne.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-cascader | ||
| 3 | + placeholder="请选择/搜索车辆" | ||
| 4 | + :options="options" | ||
| 5 | + filterable | ||
| 6 | + clearable | ||
| 7 | + :props="prop" | ||
| 8 | + v-model="valueList" | ||
| 9 | + @change="getValue"> | ||
| 10 | + </el-cascader> | ||
| 11 | +</template> | ||
| 12 | + | ||
| 13 | +<script> | ||
| 14 | +//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等), | ||
| 15 | +//例如:import 《组件名称》 from '《组件路径》, | ||
| 16 | + export default { | ||
| 17 | + //import引入的组件需要注入到对象中才能使用" | ||
| 18 | + components: {}, | ||
| 19 | + props: { | ||
| 20 | + value: { | ||
| 21 | + type: Array, | ||
| 22 | + default: [] | ||
| 23 | + } | ||
| 24 | + }, | ||
| 25 | + data() { | ||
| 26 | + //这里存放数据" | ||
| 27 | + return { | ||
| 28 | + options: [], | ||
| 29 | + prop: { | ||
| 30 | + value: 'sim', | ||
| 31 | + label: `name`, | ||
| 32 | + children: 'children' | ||
| 33 | + }, | ||
| 34 | + | ||
| 35 | + }; | ||
| 36 | + }, | ||
| 37 | + //计算属性 类似于data概念", | ||
| 38 | + computed: { | ||
| 39 | + valueList: { | ||
| 40 | + get(){ | ||
| 41 | + let value = this.value; | ||
| 42 | + if (value || value === null || value.length === 0) { | ||
| 43 | + return value | ||
| 44 | + } | ||
| 45 | + return value[ value.length - 1 ]; | ||
| 46 | + }, | ||
| 47 | + set(val){ | ||
| 48 | + if (val || val === null || val.length === 0) { | ||
| 49 | + this.$emit("input",val) | ||
| 50 | + } | ||
| 51 | + return val[ val.length - 1 ] | ||
| 52 | + } | ||
| 53 | + } | ||
| 54 | + }, | ||
| 55 | + //监控data中的数据变化", | ||
| 56 | + watch: {}, | ||
| 57 | + //方法集合", | ||
| 58 | + methods: { | ||
| 59 | + getValue(val){ | ||
| 60 | + console.log(val) | ||
| 61 | + }, | ||
| 62 | + /** | ||
| 63 | + * 查询级联数据列表 | ||
| 64 | + */ | ||
| 65 | + initTreeData() { | ||
| 66 | + this.$axios({ | ||
| 67 | + method: 'get', | ||
| 68 | + url: `/api/jt1078/query/car/tree/` + 100, | ||
| 69 | + }).then((res) => { | ||
| 70 | + if (res && res.data && res.data.data) { | ||
| 71 | + if (res.data.data.code == 1) { | ||
| 72 | + let data1 = res.data.data.result; | ||
| 73 | + this.addChannel(data1); | ||
| 74 | + console.log(data1) | ||
| 75 | + } else if (res.data.data.message) { | ||
| 76 | + this.$message.error(res.data.data.message); | ||
| 77 | + } | ||
| 78 | + } else { | ||
| 79 | + this.$message.error("请求错误,请刷新再试"); | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + }); | ||
| 83 | + }, | ||
| 84 | + /** | ||
| 85 | + * 整理数据结构 | ||
| 86 | + * @param treeNo | ||
| 87 | + */ | ||
| 88 | + addChannel(data) { | ||
| 89 | + for (let i in data) { | ||
| 90 | + if (data[i] && data[i].sim){ | ||
| 91 | + data[i].name = data[i].code; | ||
| 92 | + }else if (data[i].children && data[i].children.length > 0){ | ||
| 93 | + this.addChannel(data[i].children); | ||
| 94 | + } | ||
| 95 | + } | ||
| 96 | + this.options = data | ||
| 97 | + }, | ||
| 98 | + }, | ||
| 99 | + //生命周期 - 创建完成(可以访问当前this实例)", | ||
| 100 | + created() { | ||
| 101 | + this.initTreeData(); | ||
| 102 | + }, | ||
| 103 | + //生命周期 - 挂载完成(可以访问DOM元素)", | ||
| 104 | + mounted() { | ||
| 105 | + }, | ||
| 106 | + beforeCreate() { | ||
| 107 | + }, //生命周期 - 创建之前", | ||
| 108 | + beforeMount() { | ||
| 109 | + }, //生命周期 - 挂载之前", | ||
| 110 | + beforeUpdate() { | ||
| 111 | + }, //生命周期 - 更新之前", | ||
| 112 | + updated() { | ||
| 113 | + }, //生命周期 - 更新之后", | ||
| 114 | + beforeDestroy() { | ||
| 115 | + }, //生命周期 - 销毁之前", | ||
| 116 | + destroyed() { | ||
| 117 | + }, //生命周期 - 销毁完成", | ||
| 118 | + activated() { | ||
| 119 | + } //如果页面有keep-alive缓存功能,这个函数会触发", | ||
| 120 | + }; | ||
| 121 | +</script> | ||
| 122 | +<style scoped> | ||
| 123 | + | ||
| 124 | +</style> |
web_src/src/components/JT1078Components/deviceList/Device1078Tree.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="device-tree-main-box"> | ||
| 3 | + <div id="DeviceTree" style="width: 100%;height: 100%; background-color: #FFFFFF; overflow: auto"> | ||
| 4 | + <el-container> | ||
| 5 | + <el-header>设备列表</el-header> | ||
| 6 | + <el-main style="background-color: #ffffff;"> | ||
| 7 | + <el-input | ||
| 8 | + placeholder="输入关键字进行过滤" | ||
| 9 | + v-model="filterText"> | ||
| 10 | + </el-input> | ||
| 11 | + <el-tree | ||
| 12 | + class="filter-tree" | ||
| 13 | + :data="treeData" | ||
| 14 | + :props="defaultProps" | ||
| 15 | + :default-expanded-keys="expandedKeys" | ||
| 16 | + node-key="id" | ||
| 17 | + ref="tree" | ||
| 18 | + :filter-node-method="filterNode" | ||
| 19 | + :check-strictly="true" | ||
| 20 | + @node-click="nodeClick" | ||
| 21 | + @node-contextmenu="nodeContextmenu" | ||
| 22 | + @node-expand="handleNodeExpand" | ||
| 23 | + @node-collapse="handleNodeCollapse" | ||
| 24 | + style="margin-top: 10px" | ||
| 25 | + > | ||
| 26 | + <span class="custom-tree-node" slot-scope="{ node, data }"> | ||
| 27 | + <span v-if="data.abnormalStatus !== undefined && data.children && data.abnormalStatus === 1"> | ||
| 28 | + <i class="el-icon-location" style="color: #409EFF"></i>{{ `${data.name}(在线)` }} | ||
| 29 | + </span> | ||
| 30 | + <span v-if="data.abnormalStatus !== undefined && data.abnormalStatus === 20"> | ||
| 31 | + <i class="el-icon-location" style="color: #909399"></i>{{ `${data.name}(离线)` }} | ||
| 32 | + </span> | ||
| 33 | + <span v-if="data.abnormalStatus !== undefined && data.abnormalStatus === 10"> | ||
| 34 | + <i class="el-icon-location" style="color: #909399"></i>{{ `${data.name}(未接入)` }} | ||
| 35 | + </span> | ||
| 36 | + <span v-if="data.abnormalStatus === undefined && data.children "> | ||
| 37 | + {{ `${data.name}(${data.onlineData.length}/${data.children.length})` }} | ||
| 38 | + </span> | ||
| 39 | + <span v-if="data.abnormalStatus === undefined && data.children === undefined "> | ||
| 40 | + <i class="el-icon-video-camera-solid"> </i>{{ `${data.name}` }} | ||
| 41 | + </span> | ||
| 42 | + </span> | ||
| 43 | + </el-tree> | ||
| 44 | + </el-main> | ||
| 45 | + </el-container> | ||
| 46 | + </div> | ||
| 47 | + </div> | ||
| 48 | +</template> | ||
| 49 | + | ||
| 50 | +<script> | ||
| 51 | +//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等), | ||
| 52 | +//例如:import 《组件名称》 from '《组件路径》, | ||
| 53 | + | ||
| 54 | +export default { | ||
| 55 | + //import引入的组件需要注入到对象中才能使用" | ||
| 56 | + components: {}, | ||
| 57 | + props: { | ||
| 58 | + //树 数据 | ||
| 59 | + treeData: { | ||
| 60 | + type: Array, | ||
| 61 | + default: [] | ||
| 62 | + }, | ||
| 63 | + }, | ||
| 64 | + data() { | ||
| 65 | + //这里存放数据" | ||
| 66 | + return { | ||
| 67 | + //搜索值 | ||
| 68 | + filterText: '', | ||
| 69 | + //默认的prop | ||
| 70 | + defaultProps: { | ||
| 71 | + label: 'name', | ||
| 72 | + children: 'children', | ||
| 73 | + }, | ||
| 74 | + pointsList: [], | ||
| 75 | + expandedKeys: [] | ||
| 76 | + }; | ||
| 77 | + }, | ||
| 78 | + //计算属性 类似于data概念", | ||
| 79 | + computed: { | ||
| 80 | + }, | ||
| 81 | + //监控data中的数据变化", | ||
| 82 | + watch: { | ||
| 83 | + filterText(val) { | ||
| 84 | + this.$refs.tree.filter(val); | ||
| 85 | + }, | ||
| 86 | + treeData(val) { | ||
| 87 | + console.log(val); | ||
| 88 | + this.treeData = val | ||
| 89 | + } | ||
| 90 | + }, | ||
| 91 | + //方法集合", | ||
| 92 | + methods: { | ||
| 93 | + handleNodeExpand(data, node, el) { | ||
| 94 | + if (!this.expandedKeys.includes(node.key)) { | ||
| 95 | + this.expandedKeys.push(node.key); | ||
| 96 | + } | ||
| 97 | + }, | ||
| 98 | + handleNodeCollapse(data, node, el) { | ||
| 99 | + const index = this.expandedKeys.indexOf(node.key); | ||
| 100 | + if (index > -1) { | ||
| 101 | + this.expandedKeys.splice(index, 1); | ||
| 102 | + } | ||
| 103 | + }, | ||
| 104 | + /** | ||
| 105 | + * 模糊查询树 | ||
| 106 | + */ | ||
| 107 | + filterNode(value, data, node) { | ||
| 108 | + if (!value) return true; | ||
| 109 | + return this.findSearKey(node, value) | ||
| 110 | + }, | ||
| 111 | + /** | ||
| 112 | + * 点击事件 | ||
| 113 | + */ | ||
| 114 | + nodeClick(data, node, fun){ | ||
| 115 | + console.log(data) | ||
| 116 | + console.log("node ===> ", node) | ||
| 117 | + this.$emit('node-click', data, node); | ||
| 118 | + }, | ||
| 119 | + nodeContextmenu(event, data, node, fun){ | ||
| 120 | + | ||
| 121 | + }, | ||
| 122 | + //递归搜索父级是否包含关键字 | ||
| 123 | + findSearKey(node, key) { | ||
| 124 | + if (node.label.indexOf(key) !== -1) { | ||
| 125 | + return true; | ||
| 126 | + } else { | ||
| 127 | + if (node.parent.parent == null) { | ||
| 128 | + return false; | ||
| 129 | + } else { | ||
| 130 | + return this.findSearKey(node.parent, key); | ||
| 131 | + } | ||
| 132 | + } | ||
| 133 | + }, | ||
| 134 | + }, | ||
| 135 | + //生命周期 - 创建完成(可以访问当前this实例)", | ||
| 136 | + created() { | ||
| 137 | + }, | ||
| 138 | + //生命周期 - 挂载完成(可以访问DOM元素)", | ||
| 139 | + mounted() { | ||
| 140 | + }, | ||
| 141 | + beforeCreate() { | ||
| 142 | + }, //生命周期 - 创建之前", | ||
| 143 | + beforeMount() { | ||
| 144 | + }, //生命周期 - 挂载之前", | ||
| 145 | + beforeUpdate() { | ||
| 146 | + }, //生命周期 - 更新之前", | ||
| 147 | + updated() { | ||
| 148 | + }, //生命周期 - 更新之后", | ||
| 149 | + beforeDestroy() { | ||
| 150 | + }, //生命周期 - 销毁之前", | ||
| 151 | + destroyed() { | ||
| 152 | + }, //生命周期 - 销毁完成", | ||
| 153 | + activated() { | ||
| 154 | + } //如果页面有keep-alive缓存功能,这个函数会触发", | ||
| 155 | + }; | ||
| 156 | +</script> | ||
| 157 | +<style scoped> | ||
| 158 | + | ||
| 159 | +</style> |
web_src/src/components/JT1078Components/echarts/BarChart.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div :class="className" :style="{height:height,width:width}" /> | ||
| 3 | +</template> | ||
| 4 | + | ||
| 5 | +<script> | ||
| 6 | +import * as echarts from 'echarts' | ||
| 7 | +require('echarts/theme/macarons') // echarts theme | ||
| 8 | +import resize from './mixins/resize' | ||
| 9 | + | ||
| 10 | +const animationDuration = 6000 | ||
| 11 | + | ||
| 12 | +export default { | ||
| 13 | + mixins: [resize], | ||
| 14 | + props: { | ||
| 15 | + className: { | ||
| 16 | + type: String, | ||
| 17 | + default: 'chart' | ||
| 18 | + }, | ||
| 19 | + width: { | ||
| 20 | + type: String, | ||
| 21 | + default: '100%' | ||
| 22 | + }, | ||
| 23 | + height: { | ||
| 24 | + type: String, | ||
| 25 | + default: '300px' | ||
| 26 | + }, | ||
| 27 | + data: { | ||
| 28 | + type: Object, | ||
| 29 | + required: true | ||
| 30 | + } | ||
| 31 | + }, | ||
| 32 | + data() { | ||
| 33 | + return { | ||
| 34 | + chart: null | ||
| 35 | + } | ||
| 36 | + }, | ||
| 37 | + mounted() { | ||
| 38 | + this.$nextTick(() => { | ||
| 39 | + this.initChart() | ||
| 40 | + }) | ||
| 41 | + }, | ||
| 42 | + beforeDestroy() { | ||
| 43 | + if (!this.chart) { | ||
| 44 | + return | ||
| 45 | + } | ||
| 46 | + this.chart.dispose() | ||
| 47 | + this.chart = null | ||
| 48 | + }, | ||
| 49 | + methods: { | ||
| 50 | + initChart() { | ||
| 51 | + this.chart = echarts.init(this.$el, 'macarons') | ||
| 52 | + | ||
| 53 | + this.chart.setOption() | ||
| 54 | + } | ||
| 55 | + } | ||
| 56 | +} | ||
| 57 | +</script> |
web_src/src/components/JT1078Components/historical/HistoricalDataTree.vue
| 1 | <template> | 1 | <template> |
| 2 | - <el-card class="box-card" style="width: 100%;height: 100%"> | ||
| 3 | - <el-tree v-if="historyData.length > 0" :data="historyData"> | ||
| 4 | - <span class="custom-tree-node" slot-scope="{ node , data }"> | ||
| 5 | - <span> | ||
| 6 | - <el-button @click="clickButton(data)" style="margin-top: 30px;margin-left: -12px">{{ data.name }}</el-button> | ||
| 7 | - </span> | ||
| 8 | - </span> | ||
| 9 | - </el-tree> | ||
| 10 | - <el-empty v-else></el-empty> | ||
| 11 | - </el-card> | 2 | + <div style="width: 100%;height: 80vh" class="page-container"> |
| 3 | + <el-card class="box-card" > | ||
| 4 | + <div class="scroll-container"> | ||
| 5 | + <el-scrollbar style="height: 79vh"> | ||
| 6 | + <el-tree v-if="historyData.length > 0" :data="historyData" class="historical-list-tree"> | ||
| 7 | + <span class="custom-tree-node" slot-scope="{ node , data }"> | ||
| 8 | + <el-button @click="clickButton(data)" >{{ data.name }}</el-button> | ||
| 9 | + </span> | ||
| 10 | + </el-tree> | ||
| 11 | + <el-empty v-else></el-empty> | ||
| 12 | + </el-scrollbar> | ||
| 13 | + </div> | ||
| 14 | + </el-card> | ||
| 15 | + </div> | ||
| 12 | </template> | 16 | </template> |
| 13 | <script> | 17 | <script> |
| 14 | export default { | 18 | export default { |
| 15 | name: 'historical-data', | 19 | name: 'historical-data', |
| 16 | props: { | 20 | props: { |
| 17 | - historyData: {} | 21 | + historyData: { |
| 22 | + type: Array, | ||
| 23 | + default: [] | ||
| 24 | + } | ||
| 18 | }, | 25 | }, |
| 19 | //计算属性 类似于data概念", | 26 | //计算属性 类似于data概念", |
| 20 | computed: {}, | 27 | computed: {}, |
| @@ -49,11 +56,23 @@ export default { | @@ -49,11 +56,23 @@ export default { | ||
| 49 | } //如果页面有keep-alive缓存功能,这个函数会触发", | 56 | } //如果页面有keep-alive缓存功能,这个函数会触发", |
| 50 | }; | 57 | }; |
| 51 | </script> | 58 | </script> |
| 52 | -<style> | ||
| 53 | - | 59 | +<style scoped> |
| 60 | +.page-container { | ||
| 61 | + display: flex; | ||
| 62 | + flex-direction: column; | ||
| 63 | + height: 100vh; /* 视口高度的 100% */ | ||
| 64 | +} | ||
| 65 | +.box-card { | ||
| 66 | + flex-grow: 1; | ||
| 67 | + display: flex; | ||
| 68 | + flex-direction: column; | ||
| 69 | +} | ||
| 54 | 70 | ||
| 71 | +.scroll-container { | ||
| 72 | + flex-grow: 1; | ||
| 73 | + overflow: hidden; /* 确保内容不会溢出 */ | ||
| 74 | +} | ||
| 55 | /* 菜单的样式 */ | 75 | /* 菜单的样式 */ |
| 56 | - | ||
| 57 | .rMenu li { | 76 | .rMenu li { |
| 58 | width: 170px; | 77 | width: 170px; |
| 59 | list-style: none outside none; | 78 | list-style: none outside none; |
| @@ -66,9 +85,11 @@ export default { | @@ -66,9 +85,11 @@ export default { | ||
| 66 | color: #EEE; | 85 | color: #EEE; |
| 67 | background-color: #666; | 86 | background-color: #666; |
| 68 | } | 87 | } |
| 69 | -.el-tree-node__content { | ||
| 70 | - padding-bottom: 30px; | 88 | +.historical-list-tree >>> .el-tree-node__content { |
| 89 | + padding: 15px; | ||
| 71 | height: 20px; | 90 | height: 20px; |
| 72 | } | 91 | } |
| 73 | - | 92 | +.historical-list-tree { |
| 93 | + margin: 10px 0 20px 0; | ||
| 94 | +} | ||
| 74 | </style> | 95 | </style> |
web_src/src/components/common/jessibuca.vue
| @@ -11,8 +11,6 @@ | @@ -11,8 +11,6 @@ | ||
| 11 | </div> | 11 | </div> |
| 12 | <div class="buttons-box-right"> | 12 | <div class="buttons-box-right"> |
| 13 | <span class="jessibuca-btn">{{ kBps }} kb/s</span> | 13 | <span class="jessibuca-btn">{{ kBps }} kb/s</span> |
| 14 | - <!-- <i class="iconfont icon-file-record1 jessibuca-btn"></i>--> | ||
| 15 | - <!-- <i class="iconfont icon-xiangqing2 jessibuca-btn" ></i>--> | ||
| 16 | <i class="iconfont icon-camera1196054easyiconnet jessibuca-btn" @click="screenshot" | 14 | <i class="iconfont icon-camera1196054easyiconnet jessibuca-btn" @click="screenshot" |
| 17 | style="font-size: 1rem !important"></i> | 15 | style="font-size: 1rem !important"></i> |
| 18 | <i class="iconfont icon-shuaxin11 jessibuca-btn" @click="playBtnClick"></i> | 16 | <i class="iconfont icon-shuaxin11 jessibuca-btn" @click="playBtnClick"></i> |
| @@ -156,7 +154,7 @@ export default { | @@ -156,7 +154,7 @@ export default { | ||
| 156 | let _this = this; | 154 | let _this = this; |
| 157 | jessibuca.on("pause", function () { | 155 | jessibuca.on("pause", function () { |
| 158 | _this.playing = false; | 156 | _this.playing = false; |
| 159 | - | 157 | + |
| 160 | }); | 158 | }); |
| 161 | jessibuca.on("play", function () { | 159 | jessibuca.on("play", function () { |
| 162 | _this.playing = true; | 160 | _this.playing = true; |
web_src/src/components/console.vue
| @@ -65,7 +65,7 @@ import consoleNodeLoad from './console/ConsoleNodeLoad.vue' | @@ -65,7 +65,7 @@ import consoleNodeLoad from './console/ConsoleNodeLoad.vue' | ||
| 65 | import consoleDisk from './console/ConsoleDisk.vue' | 65 | import consoleDisk from './console/ConsoleDisk.vue' |
| 66 | import consoleResource from './console/ConsoleResource.vue' | 66 | import consoleResource from './console/ConsoleResource.vue' |
| 67 | import configInfo from './dialog/configInfo.vue' | 67 | import configInfo from './dialog/configInfo.vue' |
| 68 | - | 68 | +import consoleFlow from './console/ConsoleFlow.vue' |
| 69 | import echarts from 'echarts'; | 69 | import echarts from 'echarts'; |
| 70 | 70 | ||
| 71 | export default { | 71 | export default { |
| @@ -80,6 +80,7 @@ export default { | @@ -80,6 +80,7 @@ export default { | ||
| 80 | consoleDisk, | 80 | consoleDisk, |
| 81 | consoleResource, | 81 | consoleResource, |
| 82 | configInfo, | 82 | configInfo, |
| 83 | + consoleFlow, | ||
| 83 | }, | 84 | }, |
| 84 | data() { | 85 | data() { |
| 85 | return { | 86 | return { |
web_src/src/components/console/ConsoleFlow.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div id="ConsoleNodeLoad" style="width: 100%; height: 100%; background: #FFFFFF; text-align: center"> | ||
| 3 | + <car-tree :value="value" /> | ||
| 4 | + <ve-histogram ref="consoleNodeLoad" :data="chartData" :extend="extend" :settings="chartSettings" width="100%" height="100%" :legend-visible="true"></ve-histogram> | ||
| 5 | + </div> | ||
| 6 | +</template> | ||
| 7 | + | ||
| 8 | +<script> | ||
| 9 | + | ||
| 10 | +import CarTree from "../JT1078Components/cascader/CarTree.vue"; | ||
| 11 | + | ||
| 12 | +export default { | ||
| 13 | + name: 'ConsoleNodeLoad', | ||
| 14 | + components: {CarTree}, | ||
| 15 | + data() { | ||
| 16 | + return { | ||
| 17 | + value: null, | ||
| 18 | + chartData: { | ||
| 19 | + columns: [], | ||
| 20 | + rows: [] | ||
| 21 | + }, | ||
| 22 | + chartSettings: { | ||
| 23 | + labelMap: {}, | ||
| 24 | + }, | ||
| 25 | + extend: { | ||
| 26 | + title: { | ||
| 27 | + show: true, | ||
| 28 | + text: "流量统计", | ||
| 29 | + left: "center", | ||
| 30 | + top: 20, | ||
| 31 | + | ||
| 32 | + }, | ||
| 33 | + legend: { | ||
| 34 | + left: "center", | ||
| 35 | + bottom: "15px", | ||
| 36 | + }, | ||
| 37 | + label: { | ||
| 38 | + show: true, | ||
| 39 | + position: "top" | ||
| 40 | + } | ||
| 41 | + } | ||
| 42 | + }; | ||
| 43 | + }, | ||
| 44 | + mounted() { | ||
| 45 | + this.$nextTick(_ => { | ||
| 46 | + setTimeout(()=>{ | ||
| 47 | + this.$refs.consoleNodeLoad.echarts.resize() | ||
| 48 | + }, 100) | ||
| 49 | + }) | ||
| 50 | + }, | ||
| 51 | + destroyed() { | ||
| 52 | + }, | ||
| 53 | + methods: { | ||
| 54 | + setData: function(data) { | ||
| 55 | + this.chartData .rows = data; | ||
| 56 | + } | ||
| 57 | + } | ||
| 58 | +}; | ||
| 59 | +</script> |
web_src/src/components/console/ConsoleNodeLoad.vue
| @@ -6,7 +6,6 @@ | @@ -6,7 +6,6 @@ | ||
| 6 | 6 | ||
| 7 | <script> | 7 | <script> |
| 8 | 8 | ||
| 9 | - | ||
| 10 | import moment from "moment/moment"; | 9 | import moment from "moment/moment"; |
| 11 | 10 | ||
| 12 | export default { | 11 | export default { |
| @@ -55,7 +54,7 @@ export default { | @@ -55,7 +54,7 @@ export default { | ||
| 55 | }, | 54 | }, |
| 56 | methods: { | 55 | methods: { |
| 57 | setData: function(data) { | 56 | setData: function(data) { |
| 58 | - this.chartData .rows = data; | 57 | + this.chartData.rows = data; |
| 59 | } | 58 | } |
| 60 | 59 | ||
| 61 | } | 60 | } |
web_src/src/layout/UiHeader.vue
| @@ -10,6 +10,8 @@ | @@ -10,6 +10,8 @@ | ||
| 10 | 10 | ||
| 11 | <el-menu-item index="/historicalRecord">历史记录</el-menu-item> | 11 | <el-menu-item index="/historicalRecord">历史记录</el-menu-item> |
| 12 | 12 | ||
| 13 | + <el-menu-item index="/flowStatistics">流量统计</el-menu-item> | ||
| 14 | + | ||
| 13 | <el-menu-item v-if="editUser" index="/userManager">用户管理</el-menu-item> | 15 | <el-menu-item v-if="editUser" index="/userManager">用户管理</el-menu-item> |
| 14 | 16 | ||
| 15 | <!-- <el-submenu index="/setting">--> | 17 | <!-- <el-submenu index="/setting">--> |
web_src/src/router/index.js
| @@ -27,6 +27,7 @@ import web from '../components/setting/Web.vue' | @@ -27,6 +27,7 @@ import web from '../components/setting/Web.vue' | ||
| 27 | import wasmPlayer from '../components/common/jessibuca.vue' | 27 | import wasmPlayer from '../components/common/jessibuca.vue' |
| 28 | import rtcPlayer from '../components/dialog/rtcPlayer.vue' | 28 | import rtcPlayer from '../components/dialog/rtcPlayer.vue' |
| 29 | import historicalRecord from "../components/HistoricalRecord.vue"; | 29 | import historicalRecord from "../components/HistoricalRecord.vue"; |
| 30 | +import flowStatistics from "../components/FlowStatistics.vue"; | ||
| 30 | 31 | ||
| 31 | const originalPush = VueRouter.prototype.push | 32 | const originalPush = VueRouter.prototype.push |
| 32 | VueRouter.prototype.push = function push(location) { | 33 | VueRouter.prototype.push = function push(location) { |
| @@ -66,6 +67,10 @@ export default new VueRouter({ | @@ -66,6 +67,10 @@ export default new VueRouter({ | ||
| 66 | component: historicalRecord, | 67 | component: historicalRecord, |
| 67 | }, | 68 | }, |
| 68 | { | 69 | { |
| 70 | + path: '/flowStatistics', | ||
| 71 | + component: flowStatistics, | ||
| 72 | + }, | ||
| 73 | + { | ||
| 69 | path: '/minhang/deviceList', | 74 | path: '/minhang/deviceList', |
| 70 | name: 'minhang', | 75 | name: 'minhang', |
| 71 | component: minhang, | 76 | component: minhang, |
web_src/static/css/iconfont.css
| 1 | @font-face { | 1 | @font-face { |
| 2 | font-family: "iconfont"; /* Project id 1291092 */ | 2 | font-family: "iconfont"; /* Project id 1291092 */ |
| 3 | - src: url('iconfont.woff2?t=1673251105600') format('woff2'), | 3 | + src: url('../../../../wvp-jtt1078-pro/wvp-jtt1078-ui/src/assets/iconfont/iconfont.woff2?t=1673251105600') format('woff2'), |
| 4 | url('iconfont.woff?t=1673251105600') format('woff'), | 4 | url('iconfont.woff?t=1673251105600') format('woff'), |
| 5 | url('iconfont.ttf?t=1673251105600') format('truetype'); | 5 | url('iconfont.ttf?t=1673251105600') format('truetype'); |
| 6 | } | 6 | } |
web_src/static/css/iconfont.woff2 deleted
100644 → 0
No preview for this file type
web_src/static/file/推流通道导入.zip deleted
100644 → 0
No preview for this file type
web_src/static/js/config.js
| 1 | -window.baseUrl = "http://118.113.164.50:18989"; | 1 | +const baseUrl = `${window.location.protocol}//${window.location.hostname}${window.location.port ? ':' + window.location.port : ''}`; |
| 2 | + | ||
| 3 | +window.baseUrl = baseUrl; | ||
| 2 | 4 | ||
| 3 | // map组件全局参数, 注释此内容可以关闭地图功能 | 5 | // map组件全局参数, 注释此内容可以关闭地图功能 |
| 4 | window.mapParam = { | 6 | window.mapParam = { |