临时提交
This commit is contained in:
@@ -1,16 +1,9 @@
|
||||
package com.genersoft.iot.vmp.conf.security;
|
||||
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.HexUtil;
|
||||
import cn.hutool.crypto.SmUtil;
|
||||
import cn.hutool.crypto.symmetric.SM4;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.security.dto.JwtUser;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.Role;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.User;
|
||||
import com.genersoft.iot.vmp.web.custom.conf.SyTokenManager;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
@@ -18,7 +11,6 @@ import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -26,11 +18,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.util.ContentCachingRequestWrapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* jwt token 过滤器
|
||||
@@ -48,30 +36,19 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
|
||||
protected void doFilterInternal(HttpServletRequest servletRequest, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
ContentCachingRequestWrapper request = new ContentCachingRequestWrapper(servletRequest);
|
||||
// 忽略登录请求的token验证
|
||||
String requestURI = request.getRequestURI();
|
||||
if ((requestURI.startsWith("/doc.html") || requestURI.startsWith("/swagger-ui") ) && !userSetting.getDocEnable()) {
|
||||
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
if (requestURI.equalsIgnoreCase("/api/user/login")) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
if (requestURI.startsWith("/api/sy")) {
|
||||
|
||||
// 包装原始请求,缓存请求体
|
||||
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
|
||||
if (signCheck(wrappedRequest)) {
|
||||
// 使用参数签名方式校验
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, null, new ArrayList<>() );
|
||||
SecurityContextHolder.getContext().setAuthentication(token);
|
||||
chain.doFilter(wrappedRequest, response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!userSetting.getInterfaceAuthentication()) {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, null, new ArrayList<>() );
|
||||
@@ -134,88 +111,4 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
SecurityContextHolder.getContext().setAuthentication(token);
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
private boolean signCheck(ContentCachingRequestWrapper request) {
|
||||
try {
|
||||
String sign = request.getParameter("sign");
|
||||
String appKey = request.getParameter("appKey");
|
||||
String accessToken = request.getParameter("accessToken");
|
||||
String timestampStr = request.getParameter("timestamp");
|
||||
|
||||
if (sign == null || appKey == null || accessToken == null || timestampStr == null) {
|
||||
log.info("[SY-接口验签] 缺少关键参数:sign/appKey/accessToken/timestamp ");
|
||||
return false;
|
||||
}
|
||||
if (SyTokenManager.INSTANCE.appMap.get(appKey) == null) {
|
||||
log.info("[SY-接口验签] appKey {} 对应的 secret 不存在", appKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
Map<String, String[]> parameterMap = request.getParameterMap();
|
||||
// 参数排序
|
||||
Set<String> paramKeys = new TreeSet<>(parameterMap.keySet());
|
||||
|
||||
// 拼接签名信息
|
||||
// 参数拼接
|
||||
StringBuilder beforeSign = new StringBuilder();
|
||||
for (String paramKey : paramKeys) {
|
||||
if (paramKey.equals("sign")) {
|
||||
continue;
|
||||
}
|
||||
beforeSign.append(paramKey).append(parameterMap.get(paramKey)[0]);
|
||||
}
|
||||
// 如果是post请求的json消息,拼接body字符串
|
||||
if (request.getContentLength() > 0
|
||||
&& request.getMethod().equalsIgnoreCase("POST")
|
||||
&& request.getContentType().equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE)) {
|
||||
// 读取body内容
|
||||
byte[] requestBodyBytes = request.getContentAsByteArray();
|
||||
|
||||
if (requestBodyBytes.length > 0) {
|
||||
String requestBody = new String(requestBodyBytes, request.getCharacterEncoding());
|
||||
beforeSign.append(requestBody);
|
||||
}
|
||||
}
|
||||
beforeSign.append(SyTokenManager.INSTANCE.appMap.get(appKey));
|
||||
// 生成签名
|
||||
String buildSign = SmUtil.sm3(beforeSign.toString());
|
||||
if (!buildSign.equals(sign)) {
|
||||
log.info("[SY-接口验签] 失败, 加密前内容: {}", beforeSign);
|
||||
return false;
|
||||
}
|
||||
// 验证请求时间戳
|
||||
long timestamp = Long.parseLong(timestampStr);
|
||||
Instant timeInstant = Instant.ofEpochMilli(timestamp + SyTokenManager.INSTANCE.expires * 60 * 1000);
|
||||
if (timeInstant.isBefore(Instant.now())) {
|
||||
log.info("[SY-接口验签] 时间戳已经过期");
|
||||
return false;
|
||||
}
|
||||
// accessToken校验
|
||||
if (accessToken.equals(SyTokenManager.INSTANCE.adminToken)) {
|
||||
log.info("[SY-接口验签] adminToken已经默认放行");
|
||||
return true;
|
||||
}else {
|
||||
// 对token进行解密
|
||||
SM4 sm4 = SmUtil.sm4(HexUtil.decodeHex(SyTokenManager.INSTANCE.sm4Key));
|
||||
String decryptStr = sm4.decryptStr(accessToken, CharsetUtil.CHARSET_UTF_8);
|
||||
if (decryptStr == null) {
|
||||
log.info("[SY-接口验签] accessToken解密失败");
|
||||
return false;
|
||||
}
|
||||
JSONObject jsonObject = JSON.parseObject(decryptStr);
|
||||
Long expirationTime = jsonObject.getLong("expirationTime");
|
||||
if (expirationTime < System.currentTimeMillis()) {
|
||||
log.info("[SY-接口验签] accessToken 已经过期");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}catch (Exception e) {
|
||||
log.info("[SY-接口验签] 读取body失败", e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -614,7 +614,7 @@ public interface CommonGBChannelMapper {
|
||||
|
||||
|
||||
@SelectProvider(type = ChannelProvider.class, method = "queryGbChannelByChannelDeviceIdAndGbDeviceId")
|
||||
CameraChannel queryGbChannelByChannelDeviceIdAndGbDeviceId(@Param("channelDeviceId") String channelDeviceId, @Param("gbDeviceId") String gbDeviceId);
|
||||
List<CameraChannel> queryGbChannelByChannelDeviceIdAndGbDeviceId(@Param("channelDeviceId") String channelDeviceId, @Param("gbDeviceId") String gbDeviceId);
|
||||
|
||||
@SelectProvider(type = ChannelProvider.class, method = "queryListByDeviceIds")
|
||||
List<CameraChannel> queryListByDeviceIds(List<String> deviceIds);
|
||||
@@ -659,4 +659,6 @@ public interface CommonGBChannelMapper {
|
||||
|
||||
@SelectProvider(type = ChannelProvider.class, method = "queryCameraChannelByIds")
|
||||
List<CameraChannel> queryCameraChannelByIds(List<Integer> ids);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -309,13 +309,14 @@ public interface GroupMapper {
|
||||
|
||||
@Select(" <script>" +
|
||||
" SELECT " +
|
||||
" coalesce( wdc.gb_parent_id, wdc.parent_id) as deviceId," +
|
||||
" ANY_VALUE(coalesce( wdc.gb_parent_id, wdc.parent_id)) as deviceId," +
|
||||
" COUNT(*) AS allCount," +
|
||||
" SUM(CASE WHEN coalesce( wdc.gb_status, wdc.status) = 'ON' THEN 1 ELSE 0 END) AS onlineCount" +
|
||||
" FROM " +
|
||||
" wvp_device_channel wdc " +
|
||||
" where coalesce( wdc.gb_parent_id, wdc.parent_id) in " +
|
||||
" <foreach collection='groupList' item='item' open='(' separator=',' close=')' > #{item.deviceId}</foreach>" +
|
||||
" GROUP BY coalesce(wdc.gb_parent_id, wdc.parent_id)" +
|
||||
"</script>")
|
||||
List<CameraCount> queryCountWithChild(List<CameraGroup> groupList);
|
||||
}
|
||||
|
||||
@@ -216,10 +216,6 @@ public class ChannelProvider {
|
||||
return BASE_SQL + " where channel_type = 0 and data_type = #{dataType} and data_device_id = #{dataDeviceId}";
|
||||
}
|
||||
|
||||
public String queryCameraChannelById(Map<String, Object> params ){
|
||||
return BASE_SQL + " where id = #{gbId}";
|
||||
}
|
||||
|
||||
public String queryListByCivilCode(Map<String, Object> params ){
|
||||
StringBuilder sqlBuild = new StringBuilder();
|
||||
sqlBuild.append(BASE_SQL);
|
||||
@@ -548,12 +544,12 @@ public class ChannelProvider {
|
||||
public String queryListForSy(Map<String, Object> params ){
|
||||
StringBuilder sqlBuild = new StringBuilder();
|
||||
sqlBuild.append(BASE_SQL_FOR_CAMERA_DEVICE);
|
||||
sqlBuild.append(" where wdc.channel_type = 0 AND (wdc.gb_ptz_type is null || wdc.gb_ptz_type != 99) AND coalesce(gb_parent_id, parent_id) = #{groupDeviceId}");
|
||||
sqlBuild.append(" where wdc.channel_type = 0 AND (wdc.gb_ptz_type is null || wdc.gb_ptz_type != 99) AND coalesce(wdc.gb_parent_id, wdc.parent_id) = #{groupDeviceId}");
|
||||
if (params.get("online") != null && (Boolean)params.get("online")) {
|
||||
sqlBuild.append(" AND coalesce(gb_status, status) = 'ON'");
|
||||
sqlBuild.append(" AND coalesce(wdc.gb_status, wdc.status) = 'ON'");
|
||||
}
|
||||
if (params.get("online") != null && !(Boolean)params.get("online")) {
|
||||
sqlBuild.append(" AND coalesce(gb_status, status) = 'OFF'");
|
||||
sqlBuild.append(" AND coalesce(wdc.gb_status, wdc.status) = 'OFF'");
|
||||
}
|
||||
|
||||
return sqlBuild.toString();
|
||||
@@ -851,7 +847,17 @@ public class ChannelProvider {
|
||||
}
|
||||
|
||||
public String queryListForSyMobile(Map<String, Object> params ){
|
||||
return BASE_SQL_FOR_CAMERA_DEVICE +
|
||||
" WHERE wdc.gb_ptz_type = 99 AND coalesce(gb_business_group_id, business_group_id) = #{business}";
|
||||
StringBuilder sqlBuild = new StringBuilder();
|
||||
sqlBuild.append(BASE_SQL_FOR_CAMERA_DEVICE);
|
||||
sqlBuild.append(" WHERE wdc.gb_ptz_type = 99 ");
|
||||
if (params.get("business") != null) {
|
||||
sqlBuild.append(" AND coalesce(gb_business_group_id, business_group_id) = #{business}");
|
||||
}
|
||||
return sqlBuild.toString();
|
||||
}
|
||||
|
||||
|
||||
public String queryCameraChannelById(Map<String, Object> params ){
|
||||
return BASE_SQL_FOR_CAMERA_DEVICE + " where wdc.id = #{gbId}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,11 +60,16 @@ public class EventPublisher {
|
||||
applicationEventPublisher.publishEvent(outEvent);
|
||||
}
|
||||
|
||||
public void channelEventPublish(CommonGBChannel deviceChannel, ChannelEvent.ChannelEventMessageType type) {
|
||||
catalogEventPublish(Collections.singletonList(deviceChannel), type);
|
||||
public void channelEventPublish(CommonGBChannel commonGBChannel, ChannelEvent.ChannelEventMessageType type) {
|
||||
channelEventPublish(Collections.singletonList(commonGBChannel), type);
|
||||
}
|
||||
|
||||
private void catalogEventPublish(List<CommonGBChannel> channelList, ChannelEvent.ChannelEventMessageType type) {
|
||||
public void channelEventPublishForUpdate(CommonGBChannel commonGBChannel, CommonGBChannel deviceChannelForOld) {
|
||||
ChannelEvent channelEvent = ChannelEvent.getInstanceForUpdate(this, Collections.singletonList(commonGBChannel), Collections.singletonList(deviceChannelForOld));
|
||||
applicationEventPublisher.publishEvent(channelEvent);
|
||||
}
|
||||
|
||||
public void channelEventPublish(List<CommonGBChannel> channelList, ChannelEvent.ChannelEventMessageType type) {
|
||||
ChannelEvent channelEvent = ChannelEvent.getInstance(this, type, channelList);
|
||||
applicationEventPublisher.publishEvent(channelEvent);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import lombok.Setter;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -26,6 +25,8 @@ public class ChannelEvent extends ApplicationEvent {
|
||||
|
||||
private List<CommonGBChannel> channels;
|
||||
|
||||
private List<CommonGBChannel> oldChannels;
|
||||
|
||||
private ChannelEventMessageType messageType;
|
||||
|
||||
|
||||
@@ -41,4 +42,12 @@ public class ChannelEvent extends ApplicationEvent {
|
||||
return channelEvent;
|
||||
}
|
||||
|
||||
public static ChannelEvent getInstanceForUpdate(Object source, List<CommonGBChannel> channelList, List<CommonGBChannel> channelListForOld) {
|
||||
ChannelEvent channelEvent = new ChannelEvent(source);
|
||||
channelEvent.setMessageType(ChannelEventMessageType.UPDATE);
|
||||
channelEvent.setChannels(channelList);
|
||||
channelEvent.setOldChannels(channelListForOld);
|
||||
return channelEvent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.genersoft.iot.vmp.gb28181.dao.GroupMapper;
|
||||
import com.genersoft.iot.vmp.gb28181.dao.PlatformChannelMapper;
|
||||
import com.genersoft.iot.vmp.gb28181.dao.RegionMapper;
|
||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||
import com.genersoft.iot.vmp.gb28181.event.channel.ChannelEvent;
|
||||
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IPlatformChannelService;
|
||||
@@ -75,7 +76,7 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
int result = commonGBChannelMapper.insert(commonGBChannel);
|
||||
try {
|
||||
// 发送通知
|
||||
eventPublisher.catalogEventPublish(null, commonGBChannel, CatalogEvent.ADD);
|
||||
eventPublisher.channelEventPublish(commonGBChannel, ChannelEvent.ChannelEventMessageType.ADD);
|
||||
} catch (Exception e) {
|
||||
log.warn("[通道移除通知] 发送失败,{}", commonGBChannel.getGbDeviceId(), e);
|
||||
}
|
||||
@@ -97,7 +98,7 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
commonGBChannelMapper.delete(gbId);
|
||||
try {
|
||||
// 发送通知
|
||||
eventPublisher.catalogEventPublish(null, channel, CatalogEvent.DEL);
|
||||
eventPublisher.channelEventPublish(channel, ChannelEvent.ChannelEventMessageType.DELETE);
|
||||
} catch (Exception e) {
|
||||
log.warn("[通道移除通知] 发送失败,{}", channel.getGbDeviceId(), e);
|
||||
}
|
||||
@@ -139,15 +140,31 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
if (channels.size() > 1) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "国标编号重复,请修改编号后保存");
|
||||
}
|
||||
CommonGBChannel oldChannel = commonGBChannelMapper.queryById(commonGBChannel.getGbId());
|
||||
commonGBChannel.setUpdateTime(DateUtil.getNow());
|
||||
int result = commonGBChannelMapper.update(commonGBChannel);
|
||||
if (result > 0) {
|
||||
try {
|
||||
// 发送通知
|
||||
eventPublisher.catalogEventPublish(null, commonGBChannel, CatalogEvent.UPDATE);
|
||||
eventPublisher.channelEventPublishForUpdate(commonGBChannel, oldChannel);
|
||||
} catch (Exception e) {
|
||||
log.warn("[更新通道通知] 发送失败,{}", commonGBChannel.getGbDeviceId(), e);
|
||||
}
|
||||
MobilePosition mobilePosition = new MobilePosition();
|
||||
mobilePosition.setLongitude(commonGBChannel.getGbLongitude());
|
||||
mobilePosition.setLatitude(commonGBChannel.getGbLatitude());
|
||||
mobilePosition.setCreateTime(DateUtil.getNow());
|
||||
mobilePosition.setDeviceId(commonGBChannel.getGbDeviceId());
|
||||
mobilePosition.setTime(DateUtil.getNow());
|
||||
mobilePosition.setAltitude(0.0);
|
||||
mobilePosition.setDirection(0.0);
|
||||
mobilePosition.setSpeed(0.0);
|
||||
mobilePosition.setChannelId(commonGBChannel.getGbId());
|
||||
try {
|
||||
eventPublisher.mobilePositionEventPublish(mobilePosition);
|
||||
}catch (Exception e) {
|
||||
log.error("[向上级转发移动位置失败] ", e);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -162,7 +179,7 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
if (result > 0) {
|
||||
try {
|
||||
// 发送通知
|
||||
eventPublisher.catalogEventPublish(null, commonGBChannel, CatalogEvent.OFF);
|
||||
eventPublisher.channelEventPublish(commonGBChannel, ChannelEvent.ChannelEventMessageType.OFFLINE);
|
||||
} catch (Exception e) {
|
||||
log.warn("[通道离线通知] 发送失败,{}", commonGBChannel.getGbDeviceId(), e);
|
||||
}
|
||||
@@ -194,7 +211,7 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
if (result > 0) {
|
||||
try {
|
||||
// 发送catalog
|
||||
eventPublisher.catalogEventPublish(null, commonGBChannelList, CatalogEvent.OFF);
|
||||
eventPublisher.channelEventPublish(commonGBChannelList, ChannelEvent.ChannelEventMessageType.OFFLINE);
|
||||
} catch (Exception e) {
|
||||
log.warn("[多个通道离线] 发送失败,数量:{}", commonGBChannelList.size(), e);
|
||||
}
|
||||
@@ -212,7 +229,7 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
if (result > 0) {
|
||||
try {
|
||||
// 发送通知
|
||||
eventPublisher.catalogEventPublish(null, commonGBChannel, CatalogEvent.ON);
|
||||
eventPublisher.channelEventPublish(commonGBChannel, ChannelEvent.ChannelEventMessageType.ONLINE);
|
||||
} catch (Exception e) {
|
||||
log.warn("[通道上线通知] 发送失败,{}", commonGBChannel.getGbDeviceId(), e);
|
||||
}
|
||||
@@ -243,7 +260,7 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
}
|
||||
try {
|
||||
// 发送catalog
|
||||
eventPublisher.catalogEventPublish(null, commonGBChannelList, CatalogEvent.ON);
|
||||
eventPublisher.channelEventPublish(commonGBChannelList, ChannelEvent.ChannelEventMessageType.ONLINE);
|
||||
} catch (Exception e) {
|
||||
log.warn("[多个通道上线] 发送失败,数量:{}", commonGBChannelList.size(), e);
|
||||
}
|
||||
@@ -274,7 +291,7 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
}
|
||||
try {
|
||||
// 发送catalog
|
||||
eventPublisher.catalogEventPublish(null, commonGBChannels, CatalogEvent.ADD);
|
||||
eventPublisher.channelEventPublish(commonGBChannels, ChannelEvent.ChannelEventMessageType.ADD);
|
||||
} catch (Exception e) {
|
||||
log.warn("[多个通道新增] 发送失败,数量:{}", commonGBChannels.size(), e);
|
||||
}
|
||||
@@ -306,6 +323,7 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
try {
|
||||
// 发送通知
|
||||
eventPublisher.catalogEventPublish(null, commonGBChannels, CatalogEvent.UPDATE);
|
||||
// eventPublisher.channelEventPublishForUpdate(commonGBChannels, ChannelEvent.ChannelEventMessageType.ADD);
|
||||
} catch (Exception e) {
|
||||
log.warn("[更新多个通道] 发送失败,{}个", commonGBChannels.size(), e);
|
||||
}
|
||||
|
||||
@@ -258,22 +258,27 @@ public class ZLMRESTfulUtils {
|
||||
param.put("schema",schema);
|
||||
}
|
||||
param.put("vhost","__defaultVhost__");
|
||||
String response = sendPost(mediaServer, "getMediaList",param, (responseStr -> {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
if (responseStr == null) {
|
||||
callback.run(ZLMResult.getFailForMediaServer());
|
||||
}else {
|
||||
ZLMResult<JSONArray> zlmResult = JSON.parseObject(responseStr, new TypeReference<ZLMResult<JSONArray>>() {});
|
||||
if (zlmResult == null) {
|
||||
RequestCallback requestCallback = null;
|
||||
if (callback != null) {
|
||||
requestCallback = (responseStr -> {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
if (responseStr == null) {
|
||||
callback.run(ZLMResult.getFailForMediaServer());
|
||||
}else {
|
||||
callback.run(zlmResult);
|
||||
}
|
||||
ZLMResult<JSONArray> zlmResult = JSON.parseObject(responseStr, new TypeReference<ZLMResult<JSONArray>>() {});
|
||||
if (zlmResult == null) {
|
||||
callback.run(ZLMResult.getFailForMediaServer());
|
||||
}else {
|
||||
callback.run(zlmResult);
|
||||
}
|
||||
|
||||
}
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
String response = sendPost(mediaServer, "getMediaList",param, requestCallback);
|
||||
if (response == null) {
|
||||
return ZLMResult.getFailForMediaServer();
|
||||
}else {
|
||||
|
||||
@@ -549,6 +549,7 @@ public class StreamPushServiceImpl implements IStreamPushService {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void batchUpdate(List<StreamPush> streamPushItemForUpdate) {
|
||||
streamPushMapper.batchUpdate(streamPushItemForUpdate);
|
||||
List<CommonGBChannel> commonGBChannels = new ArrayList<>();
|
||||
|
||||
@@ -81,7 +81,7 @@ public class ServerController {
|
||||
private IStreamProxyService proxyService;
|
||||
|
||||
|
||||
@Autowired
|
||||
@Autowired(required = false)
|
||||
private IMapService mapService;
|
||||
|
||||
@Value("${server.port}")
|
||||
|
||||
@@ -23,6 +23,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -36,6 +37,7 @@ import java.util.List;
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping(value = "/api/sy")
|
||||
@ConditionalOnProperty(value = "sy.enable", havingValue = "true")
|
||||
public class CameraChannelController {
|
||||
|
||||
@Autowired
|
||||
@@ -81,6 +83,7 @@ public class CameraChannelController {
|
||||
@Parameter(name = "geoCoordSys", description = "坐标系类型:WGS84,GCJ02、BD09")
|
||||
@Parameter(name = "status", description = "摄像头状态")
|
||||
public PageInfo<CameraChannel> queryListWithChild(@RequestParam(required = false, value = "page", defaultValue = "1" )Integer page,
|
||||
|
||||
@RequestParam(required = false, value = "count", defaultValue = "100")Integer count,
|
||||
@RequestParam(required = false) String query,
|
||||
@RequestParam(required = false) String sortName,
|
||||
@@ -292,7 +295,7 @@ public class CameraChannelController {
|
||||
@Parameter(name = "topGroupAlias", description = "分组别名")
|
||||
public PageInfo<CameraChannel> queryListForMobile(@RequestParam(required = false, value = "page", defaultValue = "1" )Integer page,
|
||||
@RequestParam(required = false, value = "count", defaultValue = "100")Integer count,
|
||||
String topGroupAlias){
|
||||
@RequestParam(required = false) String topGroupAlias){
|
||||
|
||||
return channelService.queryListForMobile(page, count, topGroupAlias);
|
||||
}
|
||||
@@ -313,7 +316,7 @@ public class CameraChannelController {
|
||||
if (streamAuthorityInfo == null
|
||||
|| streamAuthorityInfo.getCallId() == null
|
||||
|| !streamAuthorityInfo.getCallId().equals(callId)) {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "播放地址鉴权失败");
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "播放地址鉴权失败");
|
||||
}
|
||||
String host;
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
package com.genersoft.iot.vmp.web.custom.conf;
|
||||
|
||||
import jakarta.servlet.ReadListener;
|
||||
import jakarta.servlet.ServletInputStream;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 自定义请求包装器,用于缓存请求体内容
|
||||
* 解决流只能读取一次的问题
|
||||
*/
|
||||
@Slf4j
|
||||
public class CachedBodyHttpServletRequest extends HttpServletRequestWrapper {
|
||||
|
||||
private byte[] cachedBody;
|
||||
private String cachedBodyString;
|
||||
|
||||
public CachedBodyHttpServletRequest(HttpServletRequest request) {
|
||||
super(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() throws IOException {
|
||||
if (cachedBody == null) {
|
||||
cacheInputStream();
|
||||
}
|
||||
return new CachedBodyServletInputStream(cachedBody);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedReader getReader() throws IOException {
|
||||
if (cachedBodyString == null) {
|
||||
if (cachedBody == null) {
|
||||
cacheInputStream();
|
||||
}
|
||||
cachedBodyString = new String(cachedBody, StandardCharsets.UTF_8);
|
||||
}
|
||||
return new BufferedReader(new StringReader(cachedBodyString));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存的请求体内容
|
||||
*/
|
||||
public String getCachedBody() {
|
||||
if (cachedBodyString == null) {
|
||||
if (cachedBody == null) {
|
||||
try {
|
||||
cacheInputStream();
|
||||
} catch (IOException e) {
|
||||
log.warn("缓存请求体失败: {}", e.getMessage());
|
||||
return "";
|
||||
}
|
||||
}
|
||||
cachedBodyString = new String(cachedBody, StandardCharsets.UTF_8);
|
||||
}
|
||||
return cachedBodyString;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存的请求体字节数组
|
||||
*/
|
||||
public byte[] getCachedBodyBytes() {
|
||||
if (cachedBody == null) {
|
||||
try {
|
||||
cacheInputStream();
|
||||
} catch (IOException e) {
|
||||
log.warn("缓存请求体失败: {}", e.getMessage());
|
||||
return new byte[0];
|
||||
}
|
||||
}
|
||||
return cachedBody;
|
||||
}
|
||||
|
||||
private void cacheInputStream() throws IOException {
|
||||
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
InputStream inputStream = super.getInputStream()) {
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
baos.write(buffer, 0, bytesRead);
|
||||
}
|
||||
cachedBody = baos.toByteArray();
|
||||
log.debug("成功缓存请求体,长度: {}", cachedBody.length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义 ServletInputStream 实现
|
||||
*/
|
||||
private static class CachedBodyServletInputStream extends ServletInputStream {
|
||||
private final ByteArrayInputStream inputStream;
|
||||
|
||||
public CachedBodyServletInputStream(byte[] body) {
|
||||
this.inputStream = new ByteArrayInputStream(body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return inputStream.available() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadListener(ReadListener readListener) {
|
||||
// 不需要实现
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return inputStream.read();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package com.genersoft.iot.vmp.web.custom.conf;
|
||||
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.HexUtil;
|
||||
import cn.hutool.crypto.SmUtil;
|
||||
import cn.hutool.crypto.symmetric.SM4;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.sip.message.Response;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* sign token 过滤器
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@ConditionalOnProperty(value = "sy.enable", havingValue = "true")
|
||||
public class SignAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
private final static String WSHeader = "sec-websocket-protocol";
|
||||
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest servletRequest, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
// 忽略登录请求的token验证
|
||||
String requestURI = servletRequest.getRequestURI();
|
||||
// 包装原始请求,缓存请求体
|
||||
CachedBodyHttpServletRequest request = new CachedBodyHttpServletRequest(servletRequest);
|
||||
if (!requestURI.startsWith("/api/sy")) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
// 设置响应内容类型
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
|
||||
try {
|
||||
String sign = request.getParameter("sign");
|
||||
String appKey = request.getParameter("appKey");
|
||||
String accessToken = request.getParameter("accessToken");
|
||||
String timestampStr = request.getParameter("timestamp");
|
||||
|
||||
if (sign == null || appKey == null || accessToken == null || timestampStr == null) {
|
||||
log.info("[SY-接口验签] 缺少关键参数:sign/appKey/accessToken/timestamp, 请求地址: {} ", requestURI);
|
||||
response.setStatus(Response.OK);
|
||||
PrintWriter out = response.getWriter();
|
||||
out.println(getErrorResult(6017, "缺少关键参数"));
|
||||
out.close();
|
||||
return;
|
||||
}
|
||||
if (SyTokenManager.INSTANCE.appMap.get(appKey) == null) {
|
||||
log.info("[SY-接口验签] appKey {} 对应的 secret 不存在, 请求地址: {} ", appKey, requestURI);
|
||||
response.setStatus(Response.OK);
|
||||
PrintWriter out = response.getWriter();
|
||||
out.println(getErrorResult(6017, "缺少关键参数"));
|
||||
out.close();
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, String[]> parameterMap = request.getParameterMap();
|
||||
// 参数排序
|
||||
Set<String> paramKeys = new TreeSet<>(parameterMap.keySet());
|
||||
|
||||
// 拼接签名信息
|
||||
// 参数拼接
|
||||
StringBuilder beforeSign = new StringBuilder();
|
||||
for (String paramKey : paramKeys) {
|
||||
if (paramKey.equals("sign")) {
|
||||
continue;
|
||||
}
|
||||
beforeSign.append(paramKey).append(parameterMap.get(paramKey)[0]);
|
||||
}
|
||||
// 如果是post请求的json消息,拼接body字符串
|
||||
if (request.getContentLength() > 0
|
||||
&& request.getMethod().equalsIgnoreCase("POST")
|
||||
&& request.getContentType().equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE)) {
|
||||
// 读取body内容 - 使用自定义缓存机制
|
||||
String requestBody = request.getCachedBody();
|
||||
if (!ObjectUtils.isEmpty(requestBody)) {
|
||||
beforeSign.append(requestBody);
|
||||
log.debug("[SY-接口验签] 读取到请求体内容,长度: {}", requestBody.length());
|
||||
} else {
|
||||
log.warn("[SY-接口验签] 请求体内容为空");
|
||||
}
|
||||
}
|
||||
beforeSign.append(SyTokenManager.INSTANCE.appMap.get(appKey));
|
||||
// 生成签名
|
||||
String buildSign = SmUtil.sm3(beforeSign.toString());
|
||||
if (!buildSign.equals(sign)) {
|
||||
log.info("[SY-接口验签] 失败,加密前内容: {}, 请求地址: {} ", beforeSign, requestURI);
|
||||
response.setStatus(Response.OK);
|
||||
PrintWriter out = response.getWriter();
|
||||
out.println(getErrorResult(6017, "接口鉴权失败"));
|
||||
out.close();
|
||||
return;
|
||||
}
|
||||
// 验证请求时间戳
|
||||
long timestamp = Long.parseLong(timestampStr);
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
if (currentTimeMillis > SyTokenManager.INSTANCE.expires * 60 * 1000 + timestamp ) {
|
||||
log.info("[SY-接口验签] 时间戳已经过期, 请求时间戳:{}, 当前时间: {}, 过期时间: {}, 请求地址: {} ", timestamp, currentTimeMillis, timestamp + SyTokenManager.INSTANCE.expires * 60 * 1000, requestURI);
|
||||
response.setStatus(Response.OK);
|
||||
PrintWriter out = response.getWriter();
|
||||
out.println(getErrorResult(6016, "接口过期"));
|
||||
out.close();
|
||||
return;
|
||||
}
|
||||
// accessToken校验
|
||||
if (accessToken.equals(SyTokenManager.INSTANCE.adminToken)) {
|
||||
log.info("[SY-接口验签] adminToken已经默认放行, 请求地址: {} ", requestURI);
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}else {
|
||||
// 对token进行解密
|
||||
SM4 sm4 = SmUtil.sm4(HexUtil.decodeHex(SyTokenManager.INSTANCE.sm4Key));
|
||||
String decryptStr = sm4.decryptStr(accessToken, CharsetUtil.CHARSET_UTF_8);
|
||||
if (decryptStr == null) {
|
||||
log.info("[SY-接口验签] accessToken解密失败, 请求地址: {} ", requestURI);
|
||||
response.setStatus(Response.OK);
|
||||
PrintWriter out = response.getWriter();
|
||||
out.println(getErrorResult(6017, "接口鉴权失败"));
|
||||
out.close();
|
||||
return;
|
||||
}
|
||||
JSONObject jsonObject = JSON.parseObject(decryptStr);
|
||||
Long expirationTime = jsonObject.getLong("expirationTime");
|
||||
if (expirationTime < System.currentTimeMillis()) {
|
||||
log.info("[SY-接口验签] accessToken 已经过期, 请求地址: {} ", requestURI);
|
||||
response.setStatus(Response.OK);
|
||||
PrintWriter out = response.getWriter();
|
||||
out.println(getErrorResult(6018, "Token已过期"));
|
||||
out.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}catch (Exception e) {
|
||||
log.info("[SY-接口验签] 读取body失败, 请求地址: {} ", requestURI, e);
|
||||
response.setStatus(Response.OK);
|
||||
PrintWriter out = response.getWriter();
|
||||
out.println(getErrorResult(6017, "接口鉴权异常"));
|
||||
out.close();
|
||||
return;
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
private String getErrorResult(Integer code, String message) {
|
||||
WVPResult<Object> wvpResult = new WVPResult<>();
|
||||
wvpResult.setCode(code);
|
||||
wvpResult.setMsg(message);
|
||||
return JSON.toJSONString(wvpResult);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import com.github.xiaoymin.knife4j.core.util.Assert;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -34,6 +35,7 @@ import java.util.*;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@ConditionalOnProperty(value = "sy.enable", havingValue = "true")
|
||||
public class CameraChannelService implements CommandLineRunner {
|
||||
|
||||
private final String REDIS_GPS_MESSAGE = "VM_MSG_MOBILE_GPS";
|
||||
@@ -176,6 +178,8 @@ public class CameraChannelService implements CommandLineRunner {
|
||||
jsonObject.put("altitude", mobilePosition.getAltitude());
|
||||
jsonObject.put("direction", mobilePosition.getDirection());
|
||||
jsonObject.put("speed", mobilePosition.getSpeed());
|
||||
jsonObject.put("topGroupGAlias", cameraChannel.getTopGroupGAlias());
|
||||
jsonObject.put("groupAlias", cameraChannel.getGroupAlias());
|
||||
log.debug("[redis发送通知] 发送 移动设备位置信息移动位置 {}: {}", REDIS_GPS_MESSAGE, jsonObject.toString());
|
||||
redisTemplate.convertAndSend(REDIS_GPS_MESSAGE, jsonObject);
|
||||
}
|
||||
@@ -308,9 +312,9 @@ public class CameraChannelService implements CommandLineRunner {
|
||||
}
|
||||
|
||||
public CameraChannel queryOne(String deviceId, String deviceCode, String geoCoordSys) {
|
||||
CameraChannel channel = channelMapper.queryGbChannelByChannelDeviceIdAndGbDeviceId(deviceId, deviceCode);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
|
||||
List<CameraChannel> cameraChannels = channelMapper.queryGbChannelByChannelDeviceIdAndGbDeviceId(deviceId, deviceCode);
|
||||
Assert.isTrue(cameraChannels.isEmpty(), "通道不存在");
|
||||
CameraChannel channel = cameraChannels.get(0);
|
||||
if (geoCoordSys != null && channel.getGbLongitude() != null && channel.getGbLatitude() != null
|
||||
&& channel.getGbLongitude() > 0 && channel.getGbLatitude() > 0) {
|
||||
if (geoCoordSys.equalsIgnoreCase("GCJ02")) {
|
||||
@@ -337,8 +341,9 @@ public class CameraChannelService implements CommandLineRunner {
|
||||
* @param callback 点播结果的回放
|
||||
*/
|
||||
public void play(String deviceId, String deviceCode, ErrorCallback<CameraStreamInfo> callback) {
|
||||
CommonGBChannel channel = channelMapper.queryGbChannelByChannelDeviceIdAndGbDeviceId(deviceId, deviceCode);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
List<CameraChannel> cameraChannels = channelMapper.queryGbChannelByChannelDeviceIdAndGbDeviceId(deviceId, deviceCode);
|
||||
Assert.isTrue(cameraChannels.isEmpty(), "通道不存在");
|
||||
CameraChannel channel = cameraChannels.get(0);
|
||||
channelPlayService.play(channel, null, userSetting.getRecordSip(), (code, msg, data) -> {
|
||||
callback.run(code, msg, new CameraStreamInfo(channel, data));
|
||||
});
|
||||
@@ -350,14 +355,16 @@ public class CameraChannelService implements CommandLineRunner {
|
||||
* @param deviceCode 通道对应的国标设备的编号
|
||||
*/
|
||||
public void stopPlay(String deviceId, String deviceCode) {
|
||||
CommonGBChannel channel = channelMapper.queryGbChannelByChannelDeviceIdAndGbDeviceId(deviceId, deviceCode);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
List<CameraChannel> cameraChannels = channelMapper.queryGbChannelByChannelDeviceIdAndGbDeviceId(deviceId, deviceCode);
|
||||
Assert.isTrue(cameraChannels.isEmpty(), "通道不存在");
|
||||
CameraChannel channel = cameraChannels.get(0);
|
||||
channelPlayService.stopPlay(channel);
|
||||
}
|
||||
|
||||
public void ptz(String deviceId, String deviceCode, String command, Integer speed, ErrorCallback<String> callback) {
|
||||
CommonGBChannel channel = channelMapper.queryGbChannelByChannelDeviceIdAndGbDeviceId(deviceId, deviceCode);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
List<CameraChannel> cameraChannels = channelMapper.queryGbChannelByChannelDeviceIdAndGbDeviceId(deviceId, deviceCode);
|
||||
Assert.isTrue(cameraChannels.isEmpty(), "通道不存在");
|
||||
CameraChannel channel = cameraChannels.get(0);
|
||||
|
||||
if (speed == null) {
|
||||
speed = 50;
|
||||
@@ -412,8 +419,9 @@ public class CameraChannelService implements CommandLineRunner {
|
||||
}
|
||||
|
||||
public void updateCamera(String deviceId, String deviceCode, String name, Double longitude, Double latitude, String geoCoordSys) {
|
||||
CommonGBChannel commonGBChannel = channelMapper.queryGbChannelByChannelDeviceIdAndGbDeviceId(deviceId, deviceCode);
|
||||
Assert.notNull(commonGBChannel, "通道不存在");
|
||||
List<CameraChannel> cameraChannels = channelMapper.queryGbChannelByChannelDeviceIdAndGbDeviceId(deviceId, deviceCode);
|
||||
Assert.isTrue(cameraChannels.isEmpty(), "通道不存在");
|
||||
CameraChannel commonGBChannel = cameraChannels.get(0);
|
||||
commonGBChannel.setGbName(name);
|
||||
if (geoCoordSys != null && longitude != null && latitude != null
|
||||
&& longitude > 0 && latitude > 0) {
|
||||
@@ -540,12 +548,15 @@ public class CameraChannelService implements CommandLineRunner {
|
||||
public PageInfo<CameraChannel> queryListForMobile(Integer page, Integer count, String topGroupAlias) {
|
||||
|
||||
CameraGroup cameraGroup = groupMapper.queryGroupByAlias(topGroupAlias);
|
||||
Assert.notNull(cameraGroup, "组织结构不存在");
|
||||
|
||||
String business = null;
|
||||
if (cameraGroup != null) {
|
||||
business = cameraGroup.getDeviceId();
|
||||
}
|
||||
// 构建分页
|
||||
PageHelper.startPage(page, count);
|
||||
List<CameraChannel> all = channelMapper.queryListForSyMobile(business);
|
||||
|
||||
List<CameraChannel> all = channelMapper.queryListForSyMobile(cameraGroup.getDeviceId());
|
||||
PageInfo<CameraChannel> groupPageInfo = new PageInfo<>(all);
|
||||
List<CameraChannel> list = addIconPathAndPositionForCameraChannelList(groupPageInfo.getList(), null);
|
||||
groupPageInfo.setList(list);
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.service.IMapService;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.MapConfig;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -17,6 +18,7 @@ import java.util.List;
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@ConditionalOnProperty(value = "sy.enable", havingValue = "true")
|
||||
public class SyServiceImpl implements IMapService {
|
||||
|
||||
@Autowired
|
||||
|
||||
Reference in New Issue
Block a user