首炬大屏
parent
1c52eefe3b
commit
0b85492cdb
|
|
@ -0,0 +1,38 @@
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.njzscloud</groupId>
|
||||||
|
<artifactId>njzscloud-common</artifactId>
|
||||||
|
<version>0.0.1</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>njzscloud-common-ws</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.njzscloud</groupId>
|
||||||
|
<artifactId>njzscloud-common-core</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.njzscloud</groupId>
|
||||||
|
<artifactId>njzscloud-common-security</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-websocket</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
package com.njzscloud.common.ws.config;
|
||||||
|
|
||||||
|
import com.njzscloud.common.ws.support.ImpartialWebSocketHandler;
|
||||||
|
import com.njzscloud.common.ws.support.TokenHandshakeInterceptor;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.util.unit.DataSize;
|
||||||
|
import org.springframework.web.socket.config.annotation.EnableWebSocket;
|
||||||
|
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
|
||||||
|
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
|
||||||
|
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSocket
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@EnableConfigurationProperties(WebsocketProperties.class)
|
||||||
|
public class WebSocketAutoConfiguration implements WebSocketConfigurer {
|
||||||
|
|
||||||
|
private final WebsocketProperties websocketProperties;
|
||||||
|
|
||||||
|
// websocket-heartbeat-js
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
|
||||||
|
String path = websocketProperties.getPath();
|
||||||
|
registry.addHandler(new ImpartialWebSocketHandler(), path == null || path.isEmpty() ? "/fdx" : path)
|
||||||
|
.addInterceptors(new TokenHandshakeInterceptor())
|
||||||
|
.setAllowedOrigins("*");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ServletServerContainerFactoryBean createWebSocketContainer() {
|
||||||
|
Duration asyncSendTimeout = websocketProperties.getAsyncSendTimeout();
|
||||||
|
Duration maxSessionIdleTimeout = websocketProperties.getMaxSessionIdleTimeout();
|
||||||
|
DataSize maxTextMessageBufferSize = websocketProperties.getMaxTextMessageBufferSize();
|
||||||
|
DataSize maxBinaryMessageBufferSize = websocketProperties.getMaxBinaryMessageBufferSize();
|
||||||
|
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
|
||||||
|
|
||||||
|
if (asyncSendTimeout != null) {
|
||||||
|
long seconds = asyncSendTimeout.getSeconds();
|
||||||
|
container.setAsyncSendTimeout(seconds * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxSessionIdleTimeout != null) {
|
||||||
|
long seconds = maxSessionIdleTimeout.getSeconds();
|
||||||
|
container.setMaxSessionIdleTimeout(seconds * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxTextMessageBufferSize != null) {
|
||||||
|
long size = maxTextMessageBufferSize.toBytes();
|
||||||
|
container.setMaxTextMessageBufferSize((int) size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxBinaryMessageBufferSize != null) {
|
||||||
|
long size = maxBinaryMessageBufferSize.toBytes();
|
||||||
|
container.setMaxBinaryMessageBufferSize((int) size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.njzscloud.common.ws.config;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.util.unit.DataSize;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* websocket 配置
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ConfigurationProperties("ws")
|
||||||
|
public class WebsocketProperties {
|
||||||
|
/**
|
||||||
|
* websocket 请求地址, 默认 /fdx
|
||||||
|
*/
|
||||||
|
private String path = "/fdx";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送超时时间
|
||||||
|
*/
|
||||||
|
private Duration asyncSendTimeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会话超时时间, 默认 15min
|
||||||
|
*/
|
||||||
|
private Duration maxSessionIdleTimeout = Duration.ofMinutes(15);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文本消息缓存大小, 默认 2MB
|
||||||
|
*/
|
||||||
|
private DataSize maxTextMessageBufferSize = DataSize.ofMegabytes(2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 二进制消息缓存大小, 默认 2MB
|
||||||
|
*/
|
||||||
|
private DataSize maxBinaryMessageBufferSize = DataSize.ofMegabytes(2);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.njzscloud.common.ws.support;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 常量
|
||||||
|
*/
|
||||||
|
public class Constants {
|
||||||
|
/**
|
||||||
|
* TOKEN 属性
|
||||||
|
*/
|
||||||
|
public static final String SESSION_ATTRIBUTE_TOKEN = "token";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端 Id 属性
|
||||||
|
*/
|
||||||
|
public static final String SESSION_ATTRIBUTE_CID = "cid";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户 Id 属性
|
||||||
|
*/
|
||||||
|
public static final String SESSION_ATTRIBUTE_UID = "uid";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
package com.njzscloud.common.ws.support;
|
||||||
|
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.njzscloud.common.core.ex.ExceptionMsg;
|
||||||
|
import com.njzscloud.common.core.utils.R;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.socket.CloseStatus;
|
||||||
|
import org.springframework.web.socket.TextMessage;
|
||||||
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
|
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* websocket 处理器<br/>
|
||||||
|
* 不支持分片消息<br/>
|
||||||
|
* 支持文本、二进制信息
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class ImpartialWebSocketHandler extends AbstractWebSocketHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
|
||||||
|
Wsdoor wsdoor = Wsdoor.of(session);
|
||||||
|
String cid = wsdoor.getCid();
|
||||||
|
Long uid = wsdoor.getUid();
|
||||||
|
wsdoor.send(new WsMsg()
|
||||||
|
.setEvent("connected")
|
||||||
|
.setData(R.success(
|
||||||
|
MapUtil.builder()
|
||||||
|
.put("uid", uid)
|
||||||
|
.put("cid", cid)
|
||||||
|
.build()
|
||||||
|
, "连接成功")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
|
||||||
|
Wsdoor wsdoor = Wsdoor.of(session);
|
||||||
|
WsMsg wsMsg = WsMsg.of(wsdoor, message);
|
||||||
|
|
||||||
|
if (wsMsg == null
|
||||||
|
|| StrUtil.isBlank(wsMsg.getAction())
|
||||||
|
|| StrUtil.isBlank(wsMsg.getEvent())) {
|
||||||
|
wsdoor.send(new WsMsg().setEvent("error")
|
||||||
|
.setData(R.failed(ExceptionMsg.CLI_ERR_MSG, "消息格式错误")));
|
||||||
|
session.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String action = wsMsg.getAction();
|
||||||
|
|
||||||
|
if (!Websocket.ACTION_PUBLISH.equals(action)
|
||||||
|
&& !Websocket.ACTION_PING.equals(action)
|
||||||
|
&& !Websocket.ACTION_UNSUBSCRIBE.equals(action)
|
||||||
|
// && !Websocket.ACTION_PONG.equals(action)
|
||||||
|
&& !Websocket.ACTION_SUBSCRIBE.equals(action)
|
||||||
|
) {
|
||||||
|
wsdoor.send(new WsMsg().setEvent("error")
|
||||||
|
.setData(R.failed(ExceptionMsg.CLI_ERR_MSG, "消息格式错误")));
|
||||||
|
session.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String event = wsMsg.getEvent();
|
||||||
|
if (Websocket.ACTION_PUBLISH.equals(action)) {
|
||||||
|
Websocket.publish(wsMsg);
|
||||||
|
} else if (Websocket.ACTION_SUBSCRIBE.equals(action)) {
|
||||||
|
WsMsg.User from = wsMsg.getFrom();
|
||||||
|
log.info("用户Id:{},客户端Id:{},订阅:{}", from.getUid(), from.getCid(), event);
|
||||||
|
Websocket.subscribe(event, wsdoor);
|
||||||
|
} else if (Websocket.ACTION_UNSUBSCRIBE.equals(action)) {
|
||||||
|
WsMsg.User from = wsMsg.getFrom();
|
||||||
|
log.info("用户Id:{},客户端Id:{},取消订阅:{}", from.getUid(), from.getCid(), event);
|
||||||
|
Websocket.unsubscribe(event, wsdoor);
|
||||||
|
} else {
|
||||||
|
wsdoor.send(new WsMsg().setAction(Websocket.ACTION_PONG));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
|
||||||
|
Wsdoor wsdoor = Wsdoor.of(session);
|
||||||
|
String cid = wsdoor.getCid();
|
||||||
|
Long uid = wsdoor.getUid();
|
||||||
|
log.error("连接失败: {} {}", cid, uid, exception);
|
||||||
|
Websocket.unsubscribe(wsdoor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
|
||||||
|
Wsdoor wsdoor = Wsdoor.of(session);
|
||||||
|
String cid = wsdoor.getCid();
|
||||||
|
Long uid = wsdoor.getUid();
|
||||||
|
log.info("连接关闭: {} {} {}", cid, uid, closeStatus);
|
||||||
|
Websocket.unsubscribe(wsdoor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
package com.njzscloud.common.ws.support;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.njzscloud.common.core.tuple.Tuple2;
|
||||||
|
import com.njzscloud.common.security.support.Token;
|
||||||
|
import com.njzscloud.common.security.support.UserDetail;
|
||||||
|
import com.njzscloud.common.security.util.SecurityUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
|
import org.springframework.http.server.ServerHttpResponse;
|
||||||
|
import org.springframework.http.server.ServletServerHttpRequest;
|
||||||
|
import org.springframework.http.server.ServletServerHttpResponse;
|
||||||
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
|
import org.springframework.web.socket.server.HandshakeInterceptor;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
// TODO TOKEN 处理器
|
||||||
|
|
||||||
|
/**
|
||||||
|
* websocket Token 拦截器<br/>
|
||||||
|
* 子协议格式: Auth [token],[cid], 如: Auth aimsn,niosdawq<br/>
|
||||||
|
* token: 用户登录凭证; cid: 客户端号, 推荐使用 token Id
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class TokenHandshakeInterceptor implements HandshakeInterceptor {
|
||||||
|
private static final String SEC_WEB_SOCKET_PROTOCOL = "Sec-WebSocket-Protocol";
|
||||||
|
private static final String Authorization = "authorization";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse serverHttpResponse, WebSocketHandler wsHandler, Map<String, Object> attributes) {
|
||||||
|
try {
|
||||||
|
HttpServletRequest req = ((ServletServerHttpRequest) request).getServletRequest();
|
||||||
|
String authorization = req.getParameter(Authorization);
|
||||||
|
// if (StrUtil.isBlank(authorization)) return false;
|
||||||
|
|
||||||
|
Tuple2<Long, String> resolved = this.resolve(authorization);
|
||||||
|
if (resolved == null) return false;
|
||||||
|
Long uid = resolved.get_0();
|
||||||
|
String cid = resolved.get_1();
|
||||||
|
attributes.put(Constants.SESSION_ATTRIBUTE_TOKEN, StrUtil.isBlank(authorization) ? cid : authorization);
|
||||||
|
attributes.put(Constants.SESSION_ATTRIBUTE_CID, cid);
|
||||||
|
attributes.put(Constants.SESSION_ATTRIBUTE_UID, uid);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[Websocket 拦截器] 数据解析失败", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
|
||||||
|
try {
|
||||||
|
HttpServletRequest httpRequest = ((ServletServerHttpRequest) request).getServletRequest();
|
||||||
|
HttpServletResponse httpResponse = ((ServletServerHttpResponse) response).getServletResponse();
|
||||||
|
String token = httpRequest.getHeader(SEC_WEB_SOCKET_PROTOCOL);
|
||||||
|
if (StrUtil.isNotEmpty(token)) {
|
||||||
|
httpResponse.addHeader(SEC_WEB_SOCKET_PROTOCOL, token);
|
||||||
|
}
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
log.error("[Websocket 拦截器] 类型转换失败: {}、{}", request.getClass(), response.getClass(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Tuple2<Long, String> resolve(String tokenStr) {
|
||||||
|
if (StrUtil.isBlank(tokenStr)) return Tuple2.create(1L, IdUtil.fastSimpleUUID());
|
||||||
|
UserDetail userDetail = SecurityUtil.parseToken(tokenStr);
|
||||||
|
if (userDetail == null) return null;
|
||||||
|
Token token = userDetail.getToken();
|
||||||
|
if (token == null) return null;
|
||||||
|
return Tuple2.create(userDetail.getUserId(), token.getTid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.njzscloud.common.ws.support;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
public @interface WSListener {
|
||||||
|
String value();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,175 @@
|
||||||
|
package com.njzscloud.common.ws.support;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* websocket 工具
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class Websocket {
|
||||||
|
|
||||||
|
public static final String ACTION_PUBLISH = "publish";
|
||||||
|
public static final String ACTION_PING = "ping";
|
||||||
|
public static final String ACTION_PONG = "pong";
|
||||||
|
public static final String ACTION_SUBSCRIBE = "subscribe";
|
||||||
|
public static final String ACTION_UNSUBSCRIBE = "unsubscribe";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端事件订阅列表
|
||||||
|
*/
|
||||||
|
static final ConcurrentHashMap<String, List<Wsdoor>> EVENT_CACHE = new ConcurrentHashMap<>();
|
||||||
|
static final ReentrantReadWriteLock EVENT_CACHE_LOCK = new ReentrantReadWriteLock();
|
||||||
|
static final ReentrantReadWriteLock.ReadLock EVENT_CACHE_READ_LOCK = EVENT_CACHE_LOCK.readLock();
|
||||||
|
static final ReentrantReadWriteLock.WriteLock EVENT_CACHE_WRITE_LOCK = EVENT_CACHE_LOCK.writeLock();
|
||||||
|
|
||||||
|
static final ConcurrentHashMap<String, List<Consumer<WsMsg>>> LISTENER_CACHE = new ConcurrentHashMap<>();
|
||||||
|
static final ReentrantReadWriteLock LISTENER_CACHE_LOCK = new ReentrantReadWriteLock();
|
||||||
|
static final ReentrantReadWriteLock.ReadLock LISTENER_CACHE_READ_LOCK = LISTENER_CACHE_LOCK.readLock();
|
||||||
|
static final ReentrantReadWriteLock.WriteLock LISTENER_CACHE_WRITE_LOCK = LISTENER_CACHE_LOCK.writeLock();
|
||||||
|
|
||||||
|
public static boolean publish(WsMsg wsMsg) {
|
||||||
|
wsMsg.setAction(ACTION_PUBLISH);
|
||||||
|
// 总数,成功数
|
||||||
|
Integer[] success = {0, 0};
|
||||||
|
String event = wsMsg.getEvent();
|
||||||
|
List<WsMsg.User> to = wsMsg.getTo();
|
||||||
|
Set<Long> uids;
|
||||||
|
Set<String> cids;
|
||||||
|
if (CollUtil.isNotEmpty(to)) {
|
||||||
|
uids = to.stream().map(WsMsg.User::getUid).collect(Collectors.toSet());
|
||||||
|
cids = to.stream().map(WsMsg.User::getCid).collect(Collectors.toSet());
|
||||||
|
} else {
|
||||||
|
uids = Collections.emptySet();
|
||||||
|
cids = Collections.emptySet();
|
||||||
|
}
|
||||||
|
EVENT_CACHE_READ_LOCK.lock();
|
||||||
|
try {
|
||||||
|
EVENT_CACHE.computeIfPresent(event, (k, v) -> {
|
||||||
|
if (CollUtil.isEmpty(v)) return v;
|
||||||
|
List<Wsdoor> wsdoors = v;
|
||||||
|
if (!uids.isEmpty() || !cids.isEmpty()) {
|
||||||
|
wsdoors = v.stream().filter(it -> {
|
||||||
|
Long uid = it.getUid();
|
||||||
|
String cid = it.getCid();
|
||||||
|
return cids.contains(cid) || uids.contains(uid);
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
success[1] = wsdoors.size();
|
||||||
|
for (Wsdoor wsdoor : wsdoors) {
|
||||||
|
boolean send = wsdoor.send(wsMsg);
|
||||||
|
if (send) success[1] = success[1] + 1;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
EVENT_CACHE_READ_LOCK.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
LISTENER_CACHE_READ_LOCK.lock();
|
||||||
|
try {
|
||||||
|
LISTENER_CACHE.computeIfPresent(event, (k, v) -> {
|
||||||
|
if (CollUtil.isEmpty(v)) return v;
|
||||||
|
success[1] = success[1] + v.size();
|
||||||
|
for (Consumer<WsMsg> listener : v) {
|
||||||
|
try {
|
||||||
|
listener.accept(wsMsg);
|
||||||
|
success[1] = success[1] + 1;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("事件 {} 监听方法执行异常", event, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
LISTENER_CACHE_READ_LOCK.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return success[1] > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean publish(String event, Object data) {
|
||||||
|
return publish(new WsMsg()
|
||||||
|
.setAction(ACTION_PUBLISH)
|
||||||
|
.setEvent(event)
|
||||||
|
.setData(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void subscribe(String event, Wsdoor wsdoor) {
|
||||||
|
EVENT_CACHE_READ_LOCK.lock();
|
||||||
|
try {
|
||||||
|
EVENT_CACHE.computeIfAbsent(event, k -> new LinkedList<>());
|
||||||
|
|
||||||
|
EVENT_CACHE.computeIfPresent(event, (k, v) -> {
|
||||||
|
v.add(wsdoor);
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
EVENT_CACHE_READ_LOCK.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void unsubscribe(Wsdoor wsdoor) {
|
||||||
|
EVENT_CACHE_WRITE_LOCK.lock();
|
||||||
|
try {
|
||||||
|
EVENT_CACHE.forEach((k, v) -> {
|
||||||
|
v.removeIf(it -> it.equals(wsdoor));
|
||||||
|
});
|
||||||
|
EVENT_CACHE.entrySet().removeIf(it -> CollUtil.isEmpty(it.getValue()));
|
||||||
|
} finally {
|
||||||
|
EVENT_CACHE_WRITE_LOCK.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void unsubscribe(String event, Wsdoor wsdoor) {
|
||||||
|
EVENT_CACHE_WRITE_LOCK.lock();
|
||||||
|
try {
|
||||||
|
EVENT_CACHE.computeIfPresent(event, (k, v) -> {
|
||||||
|
v.removeIf(it -> it.equals(wsdoor));
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
EVENT_CACHE.entrySet().removeIf(it -> CollUtil.isEmpty(it.getValue()));
|
||||||
|
} finally {
|
||||||
|
EVENT_CACHE_WRITE_LOCK.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统内部专用订阅, 用于系统事件通知<br/>
|
||||||
|
*
|
||||||
|
* @param event 事件名称
|
||||||
|
*/
|
||||||
|
public static void subscribe(String event, Consumer<WsMsg> listener) {
|
||||||
|
LISTENER_CACHE_READ_LOCK.lock();
|
||||||
|
try {
|
||||||
|
LISTENER_CACHE.computeIfAbsent(event, k -> new LinkedList<>());
|
||||||
|
LISTENER_CACHE.computeIfPresent(event, (k, v) -> {
|
||||||
|
v.add(listener);
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
LISTENER_CACHE_READ_LOCK.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void unsubscribe(String event, Consumer<WsMsg> listener) {
|
||||||
|
LISTENER_CACHE_READ_LOCK.lock();
|
||||||
|
try {
|
||||||
|
LISTENER_CACHE.computeIfPresent(event, (k, v) -> {
|
||||||
|
v.removeIf(it -> it == listener);
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
LISTENER_CACHE_READ_LOCK.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
package com.njzscloud.common.ws.support;
|
||||||
|
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.njzscloud.common.core.jackson.Jackson;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.socket.TextMessage;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* websocket 消息内容
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class WsMsg {
|
||||||
|
/**
|
||||||
|
* 发送方
|
||||||
|
*/
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
private User from;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接收方
|
||||||
|
*/
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
private List<User> to;
|
||||||
|
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private String action;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事件
|
||||||
|
*/
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private String event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据内容
|
||||||
|
*/
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
private Object data;
|
||||||
|
|
||||||
|
public static WsMsg of(Wsdoor wsdoor, TextMessage message) {
|
||||||
|
String payload = message.getPayload();
|
||||||
|
try {
|
||||||
|
WsMsg wsMsg = Jackson.toBean(payload, WsMsg.class);
|
||||||
|
if (wsMsg != null) {
|
||||||
|
wsMsg.setFrom(new User()
|
||||||
|
.setUid(wsdoor.getUid())
|
||||||
|
.setCid(wsdoor.getCid())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return wsMsg;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("WebSocket 消息反序列化失败, 数据: {}", payload, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return Jackson.toJsonStr(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T extractData(Class<T> clazz) {
|
||||||
|
return Jackson.toBean(Jackson.toJsonStr(data), clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public static class User {
|
||||||
|
/**
|
||||||
|
* 用户 Id
|
||||||
|
*/
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
private Long uid;
|
||||||
|
/**
|
||||||
|
* 客户端 Id
|
||||||
|
*/
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
private String cid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
package com.njzscloud.common.ws.support;
|
||||||
|
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.socket.TextMessage;
|
||||||
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class Wsdoor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户 Id
|
||||||
|
*/
|
||||||
|
private final Long uid;
|
||||||
|
/**
|
||||||
|
* 客户端 Id
|
||||||
|
*/
|
||||||
|
private final String cid;
|
||||||
|
/**
|
||||||
|
* TOKEN
|
||||||
|
*/
|
||||||
|
private final String token;
|
||||||
|
/**
|
||||||
|
* 连接会话
|
||||||
|
*/
|
||||||
|
private final WebSocketSession session;
|
||||||
|
|
||||||
|
private Wsdoor(WebSocketSession session) {
|
||||||
|
Map<String, Object> attributes = session.getAttributes();
|
||||||
|
this.uid = MapUtil.getLong(attributes, "uid");
|
||||||
|
this.cid = MapUtil.getStr(attributes, "cid");
|
||||||
|
this.token = MapUtil.getStr(attributes, "token");
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Wsdoor of(WebSocketSession session) {
|
||||||
|
return new Wsdoor(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Wsdoor wsdoor = (Wsdoor) o;
|
||||||
|
return Objects.equals(uid, wsdoor.uid) && Objects.equals(cid, wsdoor.cid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(uid, cid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送文本数据
|
||||||
|
*
|
||||||
|
* @param wsMsg 消息
|
||||||
|
*/
|
||||||
|
public boolean send(WsMsg wsMsg) {
|
||||||
|
try {
|
||||||
|
if (!session.isOpen()) return false;
|
||||||
|
session.sendMessage(new TextMessage(wsMsg.toString()));
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("消息发送失败", e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
org.springframework.boot.autoconfigure.EnableAutoConfiguration = \
|
||||||
|
com.njzscloud.common.ws.config.WebSocketAutoConfiguration
|
||||||
|
|
@ -1,19 +1,30 @@
|
||||||
package com.njzscloud.supervisory.statistics.controller;
|
package com.njzscloud.supervisory.statistics.controller;
|
||||||
|
|
||||||
/* @Slf4j
|
import com.njzscloud.common.core.utils.R;
|
||||||
|
import com.njzscloud.supervisory.statistics.service.SupervisionStatisticsService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@CrossOrigin
|
@CrossOrigin
|
||||||
@RestController
|
@RestController
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@RequestMapping("/statistics/supervision") */
|
@RequestMapping("/statistics/supervision")
|
||||||
public class SupervisionStatisticsController {
|
public class SupervisionStatisticsController {
|
||||||
// private final SupervisionStatisticsService supervisionStatisticsService;
|
private final SupervisionStatisticsService supervisionStatisticsService;
|
||||||
|
|
||||||
|
|
||||||
/* @GetMapping("/obtain_data")
|
@GetMapping("/obtain_data")
|
||||||
public R<?> obtainData() {
|
public R<?> obtainData() {
|
||||||
long l = System.currentTimeMillis();
|
long l = System.currentTimeMillis();
|
||||||
Map<String, Object> data = supervisionStatisticsService.obtainData();
|
Map<String, Object> data = supervisionStatisticsService.obtainData();
|
||||||
System.out.println("耗时: " + (System.currentTimeMillis() - l));
|
System.out.println("耗时: " + (System.currentTimeMillis() - l));
|
||||||
return R.success(data);
|
return R.success(data);
|
||||||
} */
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface ShouJuStatisticsMapper {
|
public interface ShouJuStatisticsMapper {
|
||||||
|
|
@ -28,4 +29,6 @@ public interface ShouJuStatisticsMapper {
|
||||||
Double disposeWeight(@Param("startTime") Long startTime, @Param("endTime") Long endTime);
|
Double disposeWeight(@Param("startTime") Long startTime, @Param("endTime") Long endTime);
|
||||||
|
|
||||||
List<OrderAmountSummary> getOrderAmountSummary(@Param("startTime") Long startTime, @Param("endTime") Long endTime);
|
List<OrderAmountSummary> getOrderAmountSummary(@Param("startTime") Long startTime, @Param("endTime") Long endTime);
|
||||||
|
|
||||||
|
List<Map<String, Object>> getChuzhi();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import com.njzscloud.supervisory.statistics.pojo.*;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface SupervisionStatisticsMapper {
|
public interface SupervisionStatisticsMapper {
|
||||||
|
|
@ -27,4 +28,7 @@ public interface SupervisionStatisticsMapper {
|
||||||
|
|
||||||
List<Project> getProjects();
|
List<Project> getProjects();
|
||||||
|
|
||||||
|
Integer getTotalCarCount();
|
||||||
|
|
||||||
|
List<Map<String, Object>> getKehuList();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,10 @@ import cn.hutool.core.date.DateTime;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.date.Week;
|
import cn.hutool.core.date.Week;
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.njzscloud.common.core.tuple.Tuple2;
|
import com.njzscloud.common.core.tuple.Tuple2;
|
||||||
import com.njzscloud.common.core.tuple.Tuple3;
|
import com.njzscloud.common.core.tuple.Tuple3;
|
||||||
|
|
@ -28,6 +32,104 @@ public class ShouJuStatisticsService implements StatisticsService {
|
||||||
private final String[] weeks = {"周一", "周二", "周三", "周四", "周五", "周六", "周日"};
|
private final String[] weeks = {"周一", "周二", "周三", "周四", "周五", "周六", "周日"};
|
||||||
private final String[] weeks_ = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
|
private final String[] weeks_ = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
|
||||||
private final String[] months = {"1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"};
|
private final String[] months = {"1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"};
|
||||||
|
private final String group = "[\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"256\",\n" +
|
||||||
|
" \"C2\": \"拆除垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"257\",\n" +
|
||||||
|
" \"C2\": \"拆除垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"263\",\n" +
|
||||||
|
" \"C2\": \"拆除垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"275\",\n" +
|
||||||
|
" \"C2\": \"拆除垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"289\",\n" +
|
||||||
|
" \"C2\": \"装修垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"292\",\n" +
|
||||||
|
" \"C2\": \"装修垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"310\",\n" +
|
||||||
|
" \"C2\": \"装修垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"316\",\n" +
|
||||||
|
" \"C2\": \"装修垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"317\",\n" +
|
||||||
|
" \"C2\": \"装修垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"319\",\n" +
|
||||||
|
" \"C2\": \"装修垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"323\",\n" +
|
||||||
|
" \"C2\": \"装修垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"324\",\n" +
|
||||||
|
" \"C2\": \"装修垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"325\",\n" +
|
||||||
|
" \"C2\": \"装修垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"327\",\n" +
|
||||||
|
" \"C2\": \"拆除垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"330\",\n" +
|
||||||
|
" \"C2\": \"拆除垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"331\",\n" +
|
||||||
|
" \"C2\": \"装修垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"334\",\n" +
|
||||||
|
" \"C2\": \"拆除垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"335\",\n" +
|
||||||
|
" \"C2\": \"装修垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"337\",\n" +
|
||||||
|
" \"C2\": \"装修垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"338\",\n" +
|
||||||
|
" \"C2\": \"拆除垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"339\",\n" +
|
||||||
|
" \"C2\": \"拆除垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"340\",\n" +
|
||||||
|
" \"C2\": \"装修垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"341\",\n" +
|
||||||
|
" \"C2\": \"装修垃圾\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"C1\": \"346\",\n" +
|
||||||
|
" \"C2\": \"拆除垃圾\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
"]";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Company getCompany() {
|
public Company getCompany() {
|
||||||
|
|
@ -298,6 +400,27 @@ public class ShouJuStatisticsService implements StatisticsService {
|
||||||
return new TodayOrderSummary();
|
return new TodayOrderSummary();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
List<Map<String, Object>> chuzhi = statisticsMapper.getChuzhi();
|
||||||
|
JSONArray objects = JSON.parseArray(group);
|
||||||
|
|
||||||
|
Map<Integer, String> map1 = GroupUtil.k_o(objects, it -> {
|
||||||
|
JSONObject object = (JSONObject) it;
|
||||||
|
return object.getInteger("C1");
|
||||||
|
}, it -> {
|
||||||
|
JSONObject object = (JSONObject) it;
|
||||||
|
return object.getString("C2");
|
||||||
|
});
|
||||||
|
|
||||||
|
HashMap<String, Integer> map2 = new HashMap<>();
|
||||||
|
|
||||||
|
for (Map<String, Object> m : chuzhi) {
|
||||||
|
Integer id = MapUtil.getInt(m, "id");
|
||||||
|
Integer weight = MapUtil.getInt(m, "weight");
|
||||||
|
String s1 = map1.get(id);
|
||||||
|
if (StrUtil.isBlank(s1)) continue;
|
||||||
|
map2.compute(s1, (k, v) -> v == null ? 0 : v + weight);
|
||||||
|
}
|
||||||
|
|
||||||
Tuple2<List<Double>, List<Double>> weekAmount_ = weekAmount.get();
|
Tuple2<List<Double>, List<Double>> weekAmount_ = weekAmount.get();
|
||||||
Tuple3<List<Double>, List<Double>, List<String>> monthAmount_ = monthAmount.get();
|
Tuple3<List<Double>, List<Double>, List<String>> monthAmount_ = monthAmount.get();
|
||||||
Tuple2<List<Double>, List<Double>> yearAmount_ = yearAmount.get();
|
Tuple2<List<Double>, List<Double>> yearAmount_ = yearAmount.get();
|
||||||
|
|
@ -320,6 +443,7 @@ public class ShouJuStatisticsService implements StatisticsService {
|
||||||
.put("days", monthAmount_.get_2())
|
.put("days", monthAmount_.get_2())
|
||||||
.put("yearAmountIn", yearAmount_.get_0())
|
.put("yearAmountIn", yearAmount_.get_0())
|
||||||
.put("yearAmountOut", yearAmount_.get_1())
|
.put("yearAmountOut", yearAmount_.get_1())
|
||||||
|
.put("chuzhi", chuzhi)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,13 @@ public class SupervisionStatisticsService {
|
||||||
|
|
||||||
CarSummary carSummary = supervisionStatisticsMapper.getCarSummary();
|
CarSummary carSummary = supervisionStatisticsMapper.getCarSummary();
|
||||||
Integer todayCarCount = supervisionStatisticsMapper.getTodayCarCount();
|
Integer todayCarCount = supervisionStatisticsMapper.getTodayCarCount();
|
||||||
|
Integer totalCarCount = supervisionStatisticsMapper.getTotalCarCount();
|
||||||
List<RegionSummary> regionSummary = supervisionStatisticsMapper.getRegionSummary();
|
List<RegionSummary> regionSummary = supervisionStatisticsMapper.getRegionSummary();
|
||||||
List<CompanySummary> companySummary = supervisionStatisticsMapper.getCompanySummary();
|
List<CompanySummary> companySummary = supervisionStatisticsMapper.getCompanySummary();
|
||||||
List<StationInfo> stationInfo = supervisionStatisticsMapper.getStationInfo();
|
List<StationInfo> stationInfo = supervisionStatisticsMapper.getStationInfo();
|
||||||
List<Order> orders = supervisionStatisticsMapper.getOrders();
|
List<Order> orders = supervisionStatisticsMapper.getOrders();
|
||||||
List<Project> projects = supervisionStatisticsMapper.getProjects();
|
List<Project> projects = supervisionStatisticsMapper.getProjects();
|
||||||
|
List<Map<String, Object>> kehu = supervisionStatisticsMapper.getKehuList();
|
||||||
|
|
||||||
return MapUtil.<String, Object>builder()
|
return MapUtil.<String, Object>builder()
|
||||||
.put("dispatchSummary", dispatchSummary == null ? new DispatchSummary() : dispatchSummary)
|
.put("dispatchSummary", dispatchSummary == null ? new DispatchSummary() : dispatchSummary)
|
||||||
|
|
@ -44,6 +46,8 @@ public class SupervisionStatisticsService {
|
||||||
.put("stationInfo", stationInfo == null ? new ArrayList<>() : stationInfo)
|
.put("stationInfo", stationInfo == null ? new ArrayList<>() : stationInfo)
|
||||||
.put("orders", orders == null ? new ArrayList<>() : orders)
|
.put("orders", orders == null ? new ArrayList<>() : orders)
|
||||||
.put("projects", projects == null ? new ArrayList<>() : projects)
|
.put("projects", projects == null ? new ArrayList<>() : projects)
|
||||||
|
.put("totalCarCount", totalCarCount == null ? 0 : totalCarCount)
|
||||||
|
.put("kehu", kehu == null ? new ArrayList<>() : kehu)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -189,4 +189,11 @@
|
||||||
</if>
|
</if>
|
||||||
LIMIT #{count}
|
LIMIT #{count}
|
||||||
</select>
|
</select>
|
||||||
|
<select id="getChuzhi" resultType="java.util.Map">
|
||||||
|
SELECT b.id, a.weight
|
||||||
|
FROM ba_order a
|
||||||
|
INNER JOIN ba_goods b ON b.id = a.goods_id
|
||||||
|
WHERE a.status = '1'
|
||||||
|
AND YEAR (a.create_time) = YEAR (CURDATE())
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
||||||
|
|
@ -38,14 +38,14 @@
|
||||||
FROM (SELECT COUNT(*) c, 1 t
|
FROM (SELECT COUNT(*) c, 1 t
|
||||||
FROM ba_order a
|
FROM ba_order a
|
||||||
INNER JOIN ba_order_dispatch b ON b.order_no = a.order_no
|
INNER JOIN ba_order_dispatch b ON b.order_no = a.order_no
|
||||||
WHERE a.create_time >= UNIX_TIMESTAMP(CURDATE())
|
WHERE UNIX_TIMESTAMP(a.create_time) >= UNIX_TIMESTAMP(CURDATE())
|
||||||
AND a.create_time <![CDATA[ < ]]> UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL -24 HOUR))
|
AND UNIX_TIMESTAMP(a.create_time) <![CDATA[ < ]]> UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL -24 HOUR))
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT COUNT(*) c, 2 t
|
SELECT COUNT(*) c, 2 t
|
||||||
FROM ba_order a
|
FROM ba_order a
|
||||||
INNER JOIN ba_order_dispatch b ON b.order_no = a.order_no
|
INNER JOIN ba_order_dispatch b ON b.order_no = a.order_no
|
||||||
WHERE a.create_time >= UNIX_TIMESTAMP(CURDATE())
|
WHERE UNIX_TIMESTAMP(a.create_time) >= UNIX_TIMESTAMP(CURDATE())
|
||||||
AND a.create_time <![CDATA[ < ]]> UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL 24 HOUR))) t) tt
|
AND UNIX_TIMESTAMP(a.create_time) <![CDATA[ < ]]> UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL 24 HOUR))) t) tt
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="getDisposeTotalWeight" resultType="java.lang.Integer">
|
<select id="getDisposeTotalWeight" resultType="java.lang.Integer">
|
||||||
|
|
@ -70,8 +70,8 @@
|
||||||
SELECT COUNT(*) car_count
|
SELECT COUNT(*) car_count
|
||||||
FROM ba_order a
|
FROM ba_order a
|
||||||
INNER JOIN ba_order_dispatch b ON b.order_no = a.order_no
|
INNER JOIN ba_order_dispatch b ON b.order_no = a.order_no
|
||||||
WHERE a.create_time >= UNIX_TIMESTAMP(CURDATE())
|
WHERE UNIX_TIMESTAMP(a.create_time) >= UNIX_TIMESTAMP(CURDATE())
|
||||||
AND a.create_time <![CDATA[ < ]]> UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL 24 HOUR))
|
AND UNIX_TIMESTAMP(a.create_time) <![CDATA[ < ]]> UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL 24 HOUR))
|
||||||
AND a.status = 1
|
AND a.status = 1
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
@ -155,4 +155,24 @@
|
||||||
ORDER BY g.create_time DESC
|
ORDER BY g.create_time DESC
|
||||||
LIMIT 10
|
LIMIT 10
|
||||||
</select>
|
</select>
|
||||||
|
<select id="getTotalCarCount" resultType="java.lang.Integer">
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM ba_car
|
||||||
|
</select>
|
||||||
|
<select id="getKehuList" resultType="java.util.Map">
|
||||||
|
SELECT a.group_id,
|
||||||
|
a.username,
|
||||||
|
a.nickname,
|
||||||
|
b.name,
|
||||||
|
a.company,
|
||||||
|
a.mobile,
|
||||||
|
a.address,
|
||||||
|
a.org_code
|
||||||
|
FROM ba_user a
|
||||||
|
LEFT JOIN ba_user_group b ON b.id = a.group_id
|
||||||
|
WHERE a.company NOT LIKE '%测试%'
|
||||||
|
AND a.nickname NOT LIKE '%测试%'
|
||||||
|
ORDER BY a.createtime DESC
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
||||||
5
pom.xml
5
pom.xml
|
|
@ -57,6 +57,11 @@
|
||||||
<artifactId>njzscloud-common-sichen</artifactId>
|
<artifactId>njzscloud-common-sichen</artifactId>
|
||||||
<version>0.0.1</version>
|
<version>0.0.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.njzscloud</groupId>
|
||||||
|
<artifactId>njzscloud-common-ws</artifactId>
|
||||||
|
<version>0.0.1</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.njzscloud</groupId>
|
<groupId>com.njzscloud</groupId>
|
||||||
<artifactId>njzscloud-common-sn</artifactId>
|
<artifactId>njzscloud-common-sn</artifactId>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue