diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java index 1b8ac75..8f47b37 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.casic.missiles.modular.dto.hik.FacePic; import com.casic.missiles.modular.dto.hik.FaceSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.BlackInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.BlackInfoService; @@ -52,7 +53,7 @@ try { List pageList = blackInfoMapper.getBlackInfoListPage(page, blackInfoRequest); pageList.forEach(blackInfo ->{ - blackInfo.setBlackReasonName(dictService.getDictNameByCode("blackReason", blackInfo.getBlackReason())); + blackInfo.setBlackReasonName(dictService.getDictNameByCode(SecurityEventDict.BLACK_REASON, blackInfo.getBlackReason())); }); return pageList; } catch (DataAccessException ex) { @@ -87,8 +88,8 @@ } JSONObject dataJson = (JSONObject)resultJson.get("data"); //设置海康人脸唯一标识、人脸分组唯一标识 - blackInfo.setIndexCode((String) dataJson.get("indexCode")); - blackInfo.setFaceGroupIndexCode((String) dataJson.get("faceGroupIndexCode")); + blackInfo.setIndexCode(String.valueOf(dataJson.get("indexCode"))); + blackInfo.setFaceGroupIndexCode(String.valueOf(dataJson.get("faceGroupIndexCode"))); //保存图片到本地 String picUrl = fileService.saveFile(blackInfo.getPicture()); blackInfo.setPicture(picUrl); diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java index 1b8ac75..8f47b37 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.casic.missiles.modular.dto.hik.FacePic; import com.casic.missiles.modular.dto.hik.FaceSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.BlackInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.BlackInfoService; @@ -52,7 +53,7 @@ try { List pageList = blackInfoMapper.getBlackInfoListPage(page, blackInfoRequest); pageList.forEach(blackInfo ->{ - blackInfo.setBlackReasonName(dictService.getDictNameByCode("blackReason", blackInfo.getBlackReason())); + blackInfo.setBlackReasonName(dictService.getDictNameByCode(SecurityEventDict.BLACK_REASON, blackInfo.getBlackReason())); }); return pageList; } catch (DataAccessException ex) { @@ -87,8 +88,8 @@ } JSONObject dataJson = (JSONObject)resultJson.get("data"); //设置海康人脸唯一标识、人脸分组唯一标识 - blackInfo.setIndexCode((String) dataJson.get("indexCode")); - blackInfo.setFaceGroupIndexCode((String) dataJson.get("faceGroupIndexCode")); + blackInfo.setIndexCode(String.valueOf(dataJson.get("indexCode"))); + blackInfo.setFaceGroupIndexCode(String.valueOf(dataJson.get("faceGroupIndexCode"))); //保存图片到本地 String picUrl = fileService.saveFile(blackInfo.getPicture()); blackInfo.setPicture(picUrl); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java index d1057e5..6fa536c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java @@ -7,6 +7,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.CaseInfoMapper; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.CaseInfoService; import lombok.extern.slf4j.Slf4j; @@ -45,10 +46,10 @@ try { List pageList = caseInfoMapper.getCaseInfoListPage(page, caseInfoRequest); pageList.forEach(caseInfo ->{ - caseInfo.setStatusName(dictService.getDictNameByCode("caseStatus", caseInfo.getStatus())); - caseInfo.setPositionName(dictService.getDictNameByCode("devicePosition", caseInfo.getPosition())); - caseInfo.setAreaName(dictService.getDictNameByCode("deviceArea", caseInfo.getArea())); - caseInfo.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", caseInfo.getIsKeyArea())); + caseInfo.setStatusName(dictService.getDictNameByCode(SecurityEventDict.CASE_STATUS, caseInfo.getStatus())); + caseInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, caseInfo.getPosition())); + caseInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, caseInfo.getArea())); + caseInfo.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, caseInfo.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -108,4 +109,9 @@ } return list; } + + @Override + public boolean insertCaseInfoBatch(List caseInfos) { + return this.saveBatch(caseInfos); + } } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java index 1b8ac75..8f47b37 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.casic.missiles.modular.dto.hik.FacePic; import com.casic.missiles.modular.dto.hik.FaceSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.BlackInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.BlackInfoService; @@ -52,7 +53,7 @@ try { List pageList = blackInfoMapper.getBlackInfoListPage(page, blackInfoRequest); pageList.forEach(blackInfo ->{ - blackInfo.setBlackReasonName(dictService.getDictNameByCode("blackReason", blackInfo.getBlackReason())); + blackInfo.setBlackReasonName(dictService.getDictNameByCode(SecurityEventDict.BLACK_REASON, blackInfo.getBlackReason())); }); return pageList; } catch (DataAccessException ex) { @@ -87,8 +88,8 @@ } JSONObject dataJson = (JSONObject)resultJson.get("data"); //设置海康人脸唯一标识、人脸分组唯一标识 - blackInfo.setIndexCode((String) dataJson.get("indexCode")); - blackInfo.setFaceGroupIndexCode((String) dataJson.get("faceGroupIndexCode")); + blackInfo.setIndexCode(String.valueOf(dataJson.get("indexCode"))); + blackInfo.setFaceGroupIndexCode(String.valueOf(dataJson.get("faceGroupIndexCode"))); //保存图片到本地 String picUrl = fileService.saveFile(blackInfo.getPicture()); blackInfo.setPicture(picUrl); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java index d1057e5..6fa536c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java @@ -7,6 +7,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.CaseInfoMapper; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.CaseInfoService; import lombok.extern.slf4j.Slf4j; @@ -45,10 +46,10 @@ try { List pageList = caseInfoMapper.getCaseInfoListPage(page, caseInfoRequest); pageList.forEach(caseInfo ->{ - caseInfo.setStatusName(dictService.getDictNameByCode("caseStatus", caseInfo.getStatus())); - caseInfo.setPositionName(dictService.getDictNameByCode("devicePosition", caseInfo.getPosition())); - caseInfo.setAreaName(dictService.getDictNameByCode("deviceArea", caseInfo.getArea())); - caseInfo.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", caseInfo.getIsKeyArea())); + caseInfo.setStatusName(dictService.getDictNameByCode(SecurityEventDict.CASE_STATUS, caseInfo.getStatus())); + caseInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, caseInfo.getPosition())); + caseInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, caseInfo.getArea())); + caseInfo.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, caseInfo.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -108,4 +109,9 @@ } return list; } + + @Override + public boolean insertCaseInfoBatch(List caseInfos) { + return this.saveBatch(caseInfos); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java index 849e4f1..9d9c731 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dao.GateGroupMapper; import com.casic.missiles.modular.dao.GroupDeviceMapper; import com.casic.missiles.modular.dto.*; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.DeviceRepairLog; import com.casic.missiles.modular.model.GateGroup; @@ -68,11 +69,11 @@ try { List pageList = deviceInfoMapper.getDeviceInfoListPage(page, deviceInfoRequest); pageList.forEach(device ->{ - device.setDevType(dictService.getDictNameByCode("deviceType", device.getDevType())); - device.setStatus(dictService.getDictNameByCode("deviceStatus", device.getStatus())); - device.setPositionName(dictService.getDictNameByCode("devicePosition", device.getPosition())); - device.setAreaName(dictService.getDictNameByCode("deviceArea", device.getArea())); - device.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", device.getIsKeyArea())); + device.setDevType(dictService.getDictNameByCode(SecurityEventDict.DEVICE_TYPE, device.getDevType())); + device.setStatus(dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, device.getStatus())); + device.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, device.getPosition())); + device.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, device.getArea())); + device.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, device.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -214,7 +215,7 @@ try { List pageList = gateGroupMapper.getGateGroupListPage(page, gateGroupRequest); pageList.forEach(gateGroup ->{ - gateGroup.setStatusName(dictService.getDictNameByCode("groupDeviceStatus", gateGroup.getStatus())); + gateGroup.setStatusName(dictService.getDictNameByCode(SecurityEventDict.GROUP_DEVICE_STATUS, gateGroup.getStatus())); }); return pageList; } catch (DataAccessException ex) { @@ -300,5 +301,11 @@ return deviceCodes; } + @Override + public List selectIndexCodesByCodes(List deviceCodes) { + List indexCodes = deviceInfoMapper.selectIndexCodesByCodes(deviceCodes); + return indexCodes; + } + } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java index 1b8ac75..8f47b37 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.casic.missiles.modular.dto.hik.FacePic; import com.casic.missiles.modular.dto.hik.FaceSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.BlackInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.BlackInfoService; @@ -52,7 +53,7 @@ try { List pageList = blackInfoMapper.getBlackInfoListPage(page, blackInfoRequest); pageList.forEach(blackInfo ->{ - blackInfo.setBlackReasonName(dictService.getDictNameByCode("blackReason", blackInfo.getBlackReason())); + blackInfo.setBlackReasonName(dictService.getDictNameByCode(SecurityEventDict.BLACK_REASON, blackInfo.getBlackReason())); }); return pageList; } catch (DataAccessException ex) { @@ -87,8 +88,8 @@ } JSONObject dataJson = (JSONObject)resultJson.get("data"); //设置海康人脸唯一标识、人脸分组唯一标识 - blackInfo.setIndexCode((String) dataJson.get("indexCode")); - blackInfo.setFaceGroupIndexCode((String) dataJson.get("faceGroupIndexCode")); + blackInfo.setIndexCode(String.valueOf(dataJson.get("indexCode"))); + blackInfo.setFaceGroupIndexCode(String.valueOf(dataJson.get("faceGroupIndexCode"))); //保存图片到本地 String picUrl = fileService.saveFile(blackInfo.getPicture()); blackInfo.setPicture(picUrl); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java index d1057e5..6fa536c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java @@ -7,6 +7,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.CaseInfoMapper; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.CaseInfoService; import lombok.extern.slf4j.Slf4j; @@ -45,10 +46,10 @@ try { List pageList = caseInfoMapper.getCaseInfoListPage(page, caseInfoRequest); pageList.forEach(caseInfo ->{ - caseInfo.setStatusName(dictService.getDictNameByCode("caseStatus", caseInfo.getStatus())); - caseInfo.setPositionName(dictService.getDictNameByCode("devicePosition", caseInfo.getPosition())); - caseInfo.setAreaName(dictService.getDictNameByCode("deviceArea", caseInfo.getArea())); - caseInfo.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", caseInfo.getIsKeyArea())); + caseInfo.setStatusName(dictService.getDictNameByCode(SecurityEventDict.CASE_STATUS, caseInfo.getStatus())); + caseInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, caseInfo.getPosition())); + caseInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, caseInfo.getArea())); + caseInfo.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, caseInfo.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -108,4 +109,9 @@ } return list; } + + @Override + public boolean insertCaseInfoBatch(List caseInfos) { + return this.saveBatch(caseInfos); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java index 849e4f1..9d9c731 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dao.GateGroupMapper; import com.casic.missiles.modular.dao.GroupDeviceMapper; import com.casic.missiles.modular.dto.*; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.DeviceRepairLog; import com.casic.missiles.modular.model.GateGroup; @@ -68,11 +69,11 @@ try { List pageList = deviceInfoMapper.getDeviceInfoListPage(page, deviceInfoRequest); pageList.forEach(device ->{ - device.setDevType(dictService.getDictNameByCode("deviceType", device.getDevType())); - device.setStatus(dictService.getDictNameByCode("deviceStatus", device.getStatus())); - device.setPositionName(dictService.getDictNameByCode("devicePosition", device.getPosition())); - device.setAreaName(dictService.getDictNameByCode("deviceArea", device.getArea())); - device.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", device.getIsKeyArea())); + device.setDevType(dictService.getDictNameByCode(SecurityEventDict.DEVICE_TYPE, device.getDevType())); + device.setStatus(dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, device.getStatus())); + device.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, device.getPosition())); + device.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, device.getArea())); + device.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, device.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -214,7 +215,7 @@ try { List pageList = gateGroupMapper.getGateGroupListPage(page, gateGroupRequest); pageList.forEach(gateGroup ->{ - gateGroup.setStatusName(dictService.getDictNameByCode("groupDeviceStatus", gateGroup.getStatus())); + gateGroup.setStatusName(dictService.getDictNameByCode(SecurityEventDict.GROUP_DEVICE_STATUS, gateGroup.getStatus())); }); return pageList; } catch (DataAccessException ex) { @@ -300,5 +301,11 @@ return deviceCodes; } + @Override + public List selectIndexCodesByCodes(List deviceCodes) { + List indexCodes = deviceInfoMapper.selectIndexCodesByCodes(deviceCodes); + return indexCodes; + } + } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java index 8a5f370..a95fff2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java @@ -8,6 +8,7 @@ import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.dao.FireEquipInfoMapper; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.FireEquipInfo; import com.casic.missiles.modular.service.FireEquipService; @@ -48,10 +49,10 @@ try { List pageList = fireEquipInfoMapper.getFireEquipInfoListPage(page, fireEquipRequest); pageList.forEach(equipInfo ->{ - equipInfo.setEquipTypeName(dictService.getDictNameByCode("equipType", equipInfo.getEquipType())); - equipInfo.setFireLevelName(dictService.getDictNameByCode("fireLevel", equipInfo.getFireLevel())); - equipInfo.setPositionName(dictService.getDictNameByCode("devicePosition", equipInfo.getPosition())); - equipInfo.setAreaName(dictService.getDictNameByCode("deviceArea", equipInfo.getArea())); + equipInfo.setEquipTypeName(dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, equipInfo.getEquipType())); + equipInfo.setFireLevelName(dictService.getDictNameByCode(SecurityEventDict.FIRE_LEVEL, equipInfo.getFireLevel())); + equipInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, equipInfo.getPosition())); + equipInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, equipInfo.getArea())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java index 1b8ac75..8f47b37 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.casic.missiles.modular.dto.hik.FacePic; import com.casic.missiles.modular.dto.hik.FaceSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.BlackInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.BlackInfoService; @@ -52,7 +53,7 @@ try { List pageList = blackInfoMapper.getBlackInfoListPage(page, blackInfoRequest); pageList.forEach(blackInfo ->{ - blackInfo.setBlackReasonName(dictService.getDictNameByCode("blackReason", blackInfo.getBlackReason())); + blackInfo.setBlackReasonName(dictService.getDictNameByCode(SecurityEventDict.BLACK_REASON, blackInfo.getBlackReason())); }); return pageList; } catch (DataAccessException ex) { @@ -87,8 +88,8 @@ } JSONObject dataJson = (JSONObject)resultJson.get("data"); //设置海康人脸唯一标识、人脸分组唯一标识 - blackInfo.setIndexCode((String) dataJson.get("indexCode")); - blackInfo.setFaceGroupIndexCode((String) dataJson.get("faceGroupIndexCode")); + blackInfo.setIndexCode(String.valueOf(dataJson.get("indexCode"))); + blackInfo.setFaceGroupIndexCode(String.valueOf(dataJson.get("faceGroupIndexCode"))); //保存图片到本地 String picUrl = fileService.saveFile(blackInfo.getPicture()); blackInfo.setPicture(picUrl); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java index d1057e5..6fa536c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java @@ -7,6 +7,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.CaseInfoMapper; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.CaseInfoService; import lombok.extern.slf4j.Slf4j; @@ -45,10 +46,10 @@ try { List pageList = caseInfoMapper.getCaseInfoListPage(page, caseInfoRequest); pageList.forEach(caseInfo ->{ - caseInfo.setStatusName(dictService.getDictNameByCode("caseStatus", caseInfo.getStatus())); - caseInfo.setPositionName(dictService.getDictNameByCode("devicePosition", caseInfo.getPosition())); - caseInfo.setAreaName(dictService.getDictNameByCode("deviceArea", caseInfo.getArea())); - caseInfo.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", caseInfo.getIsKeyArea())); + caseInfo.setStatusName(dictService.getDictNameByCode(SecurityEventDict.CASE_STATUS, caseInfo.getStatus())); + caseInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, caseInfo.getPosition())); + caseInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, caseInfo.getArea())); + caseInfo.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, caseInfo.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -108,4 +109,9 @@ } return list; } + + @Override + public boolean insertCaseInfoBatch(List caseInfos) { + return this.saveBatch(caseInfos); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java index 849e4f1..9d9c731 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dao.GateGroupMapper; import com.casic.missiles.modular.dao.GroupDeviceMapper; import com.casic.missiles.modular.dto.*; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.DeviceRepairLog; import com.casic.missiles.modular.model.GateGroup; @@ -68,11 +69,11 @@ try { List pageList = deviceInfoMapper.getDeviceInfoListPage(page, deviceInfoRequest); pageList.forEach(device ->{ - device.setDevType(dictService.getDictNameByCode("deviceType", device.getDevType())); - device.setStatus(dictService.getDictNameByCode("deviceStatus", device.getStatus())); - device.setPositionName(dictService.getDictNameByCode("devicePosition", device.getPosition())); - device.setAreaName(dictService.getDictNameByCode("deviceArea", device.getArea())); - device.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", device.getIsKeyArea())); + device.setDevType(dictService.getDictNameByCode(SecurityEventDict.DEVICE_TYPE, device.getDevType())); + device.setStatus(dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, device.getStatus())); + device.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, device.getPosition())); + device.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, device.getArea())); + device.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, device.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -214,7 +215,7 @@ try { List pageList = gateGroupMapper.getGateGroupListPage(page, gateGroupRequest); pageList.forEach(gateGroup ->{ - gateGroup.setStatusName(dictService.getDictNameByCode("groupDeviceStatus", gateGroup.getStatus())); + gateGroup.setStatusName(dictService.getDictNameByCode(SecurityEventDict.GROUP_DEVICE_STATUS, gateGroup.getStatus())); }); return pageList; } catch (DataAccessException ex) { @@ -300,5 +301,11 @@ return deviceCodes; } + @Override + public List selectIndexCodesByCodes(List deviceCodes) { + List indexCodes = deviceInfoMapper.selectIndexCodesByCodes(deviceCodes); + return indexCodes; + } + } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java index 8a5f370..a95fff2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java @@ -8,6 +8,7 @@ import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.dao.FireEquipInfoMapper; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.FireEquipInfo; import com.casic.missiles.modular.service.FireEquipService; @@ -48,10 +49,10 @@ try { List pageList = fireEquipInfoMapper.getFireEquipInfoListPage(page, fireEquipRequest); pageList.forEach(equipInfo ->{ - equipInfo.setEquipTypeName(dictService.getDictNameByCode("equipType", equipInfo.getEquipType())); - equipInfo.setFireLevelName(dictService.getDictNameByCode("fireLevel", equipInfo.getFireLevel())); - equipInfo.setPositionName(dictService.getDictNameByCode("devicePosition", equipInfo.getPosition())); - equipInfo.setAreaName(dictService.getDictNameByCode("deviceArea", equipInfo.getArea())); + equipInfo.setEquipTypeName(dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, equipInfo.getEquipType())); + equipInfo.setFireLevelName(dictService.getDictNameByCode(SecurityEventDict.FIRE_LEVEL, equipInfo.getFireLevel())); + equipInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, equipInfo.getPosition())); + equipInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, equipInfo.getArea())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java new file mode 100644 index 0000000..b47f78f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java @@ -0,0 +1,284 @@ +package com.casic.missiles.modular.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.*; +import com.casic.missiles.modular.service.HikService; +import com.casic.missiles.modular.system.model.Dict; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +@Slf4j +@Service +public class HikServiceImpl implements HikService { + + @Resource + private AbstractDictService dictService; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Override + public CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public void propertyAttendanceHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 物业人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增物业人员考勤异常"); + return; + } + } + } + + @Override + public void securityPersonnelHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 安保人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增安保人员考勤异常"); + return; + } + } + } + + @Override + public void visitorRegisterHandler(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("startTime")); + String startTime = DateUtil.formatDateTime(parse); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + VisitInfo visitInfo = new VisitInfo(); + visitInfo.setVisitorName(data.getString("personName")); + visitInfo.setVisitorGender(data.getString("sex")); + visitInfo.setVisitorPhone(data.getString("phone")); + visitInfo.setInTime(startTime); //来访时间 +// visitInfo.setOutTime(); + if("111".equals(data.getString("idType"))){ + visitInfo.setInType("身份证"); + visitInfo.setIdCard(data.getString("idNo")); + } + visitInfo.setVisitReason(data.getString("purpose")); + visitInfo.setPicUri(data.getString("captureUrl")); + visitInfo.setServerIndexCode(data.getString("svrIndexCode")); + visitInfo.setVisitPosition(deviceInfo.getPosition()); + + if(visitInfoMapper.insert(visitInfo) <= 0){ + log.error("新增访客记录异常"); + } + } + + @Override + public void visitorCheckOutHandler(JSONObject event) { + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("endTime")); + String endTime = DateUtil.formatDateTime(parse); + VisitInfo visitInfo = visitInfoMapper.selectByOrderId(data.getString("visitorId")); + if(!Objects.isNull(visitInfo)){ + visitInfo.setOutTime(endTime); + } + if(visitInfoMapper.updateById(visitInfo) <= 0){ + log.error("更新访客记录异常"); + } + } + + +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java index 1b8ac75..8f47b37 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.casic.missiles.modular.dto.hik.FacePic; import com.casic.missiles.modular.dto.hik.FaceSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.BlackInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.BlackInfoService; @@ -52,7 +53,7 @@ try { List pageList = blackInfoMapper.getBlackInfoListPage(page, blackInfoRequest); pageList.forEach(blackInfo ->{ - blackInfo.setBlackReasonName(dictService.getDictNameByCode("blackReason", blackInfo.getBlackReason())); + blackInfo.setBlackReasonName(dictService.getDictNameByCode(SecurityEventDict.BLACK_REASON, blackInfo.getBlackReason())); }); return pageList; } catch (DataAccessException ex) { @@ -87,8 +88,8 @@ } JSONObject dataJson = (JSONObject)resultJson.get("data"); //设置海康人脸唯一标识、人脸分组唯一标识 - blackInfo.setIndexCode((String) dataJson.get("indexCode")); - blackInfo.setFaceGroupIndexCode((String) dataJson.get("faceGroupIndexCode")); + blackInfo.setIndexCode(String.valueOf(dataJson.get("indexCode"))); + blackInfo.setFaceGroupIndexCode(String.valueOf(dataJson.get("faceGroupIndexCode"))); //保存图片到本地 String picUrl = fileService.saveFile(blackInfo.getPicture()); blackInfo.setPicture(picUrl); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java index d1057e5..6fa536c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java @@ -7,6 +7,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.CaseInfoMapper; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.CaseInfoService; import lombok.extern.slf4j.Slf4j; @@ -45,10 +46,10 @@ try { List pageList = caseInfoMapper.getCaseInfoListPage(page, caseInfoRequest); pageList.forEach(caseInfo ->{ - caseInfo.setStatusName(dictService.getDictNameByCode("caseStatus", caseInfo.getStatus())); - caseInfo.setPositionName(dictService.getDictNameByCode("devicePosition", caseInfo.getPosition())); - caseInfo.setAreaName(dictService.getDictNameByCode("deviceArea", caseInfo.getArea())); - caseInfo.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", caseInfo.getIsKeyArea())); + caseInfo.setStatusName(dictService.getDictNameByCode(SecurityEventDict.CASE_STATUS, caseInfo.getStatus())); + caseInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, caseInfo.getPosition())); + caseInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, caseInfo.getArea())); + caseInfo.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, caseInfo.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -108,4 +109,9 @@ } return list; } + + @Override + public boolean insertCaseInfoBatch(List caseInfos) { + return this.saveBatch(caseInfos); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java index 849e4f1..9d9c731 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dao.GateGroupMapper; import com.casic.missiles.modular.dao.GroupDeviceMapper; import com.casic.missiles.modular.dto.*; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.DeviceRepairLog; import com.casic.missiles.modular.model.GateGroup; @@ -68,11 +69,11 @@ try { List pageList = deviceInfoMapper.getDeviceInfoListPage(page, deviceInfoRequest); pageList.forEach(device ->{ - device.setDevType(dictService.getDictNameByCode("deviceType", device.getDevType())); - device.setStatus(dictService.getDictNameByCode("deviceStatus", device.getStatus())); - device.setPositionName(dictService.getDictNameByCode("devicePosition", device.getPosition())); - device.setAreaName(dictService.getDictNameByCode("deviceArea", device.getArea())); - device.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", device.getIsKeyArea())); + device.setDevType(dictService.getDictNameByCode(SecurityEventDict.DEVICE_TYPE, device.getDevType())); + device.setStatus(dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, device.getStatus())); + device.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, device.getPosition())); + device.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, device.getArea())); + device.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, device.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -214,7 +215,7 @@ try { List pageList = gateGroupMapper.getGateGroupListPage(page, gateGroupRequest); pageList.forEach(gateGroup ->{ - gateGroup.setStatusName(dictService.getDictNameByCode("groupDeviceStatus", gateGroup.getStatus())); + gateGroup.setStatusName(dictService.getDictNameByCode(SecurityEventDict.GROUP_DEVICE_STATUS, gateGroup.getStatus())); }); return pageList; } catch (DataAccessException ex) { @@ -300,5 +301,11 @@ return deviceCodes; } + @Override + public List selectIndexCodesByCodes(List deviceCodes) { + List indexCodes = deviceInfoMapper.selectIndexCodesByCodes(deviceCodes); + return indexCodes; + } + } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java index 8a5f370..a95fff2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java @@ -8,6 +8,7 @@ import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.dao.FireEquipInfoMapper; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.FireEquipInfo; import com.casic.missiles.modular.service.FireEquipService; @@ -48,10 +49,10 @@ try { List pageList = fireEquipInfoMapper.getFireEquipInfoListPage(page, fireEquipRequest); pageList.forEach(equipInfo ->{ - equipInfo.setEquipTypeName(dictService.getDictNameByCode("equipType", equipInfo.getEquipType())); - equipInfo.setFireLevelName(dictService.getDictNameByCode("fireLevel", equipInfo.getFireLevel())); - equipInfo.setPositionName(dictService.getDictNameByCode("devicePosition", equipInfo.getPosition())); - equipInfo.setAreaName(dictService.getDictNameByCode("deviceArea", equipInfo.getArea())); + equipInfo.setEquipTypeName(dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, equipInfo.getEquipType())); + equipInfo.setFireLevelName(dictService.getDictNameByCode(SecurityEventDict.FIRE_LEVEL, equipInfo.getFireLevel())); + equipInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, equipInfo.getPosition())); + equipInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, equipInfo.getArea())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java new file mode 100644 index 0000000..b47f78f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java @@ -0,0 +1,284 @@ +package com.casic.missiles.modular.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.*; +import com.casic.missiles.modular.service.HikService; +import com.casic.missiles.modular.system.model.Dict; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +@Slf4j +@Service +public class HikServiceImpl implements HikService { + + @Resource + private AbstractDictService dictService; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Override + public CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public void propertyAttendanceHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 物业人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增物业人员考勤异常"); + return; + } + } + } + + @Override + public void securityPersonnelHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 安保人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增安保人员考勤异常"); + return; + } + } + } + + @Override + public void visitorRegisterHandler(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("startTime")); + String startTime = DateUtil.formatDateTime(parse); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + VisitInfo visitInfo = new VisitInfo(); + visitInfo.setVisitorName(data.getString("personName")); + visitInfo.setVisitorGender(data.getString("sex")); + visitInfo.setVisitorPhone(data.getString("phone")); + visitInfo.setInTime(startTime); //来访时间 +// visitInfo.setOutTime(); + if("111".equals(data.getString("idType"))){ + visitInfo.setInType("身份证"); + visitInfo.setIdCard(data.getString("idNo")); + } + visitInfo.setVisitReason(data.getString("purpose")); + visitInfo.setPicUri(data.getString("captureUrl")); + visitInfo.setServerIndexCode(data.getString("svrIndexCode")); + visitInfo.setVisitPosition(deviceInfo.getPosition()); + + if(visitInfoMapper.insert(visitInfo) <= 0){ + log.error("新增访客记录异常"); + } + } + + @Override + public void visitorCheckOutHandler(JSONObject event) { + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("endTime")); + String endTime = DateUtil.formatDateTime(parse); + VisitInfo visitInfo = visitInfoMapper.selectByOrderId(data.getString("visitorId")); + if(!Objects.isNull(visitInfo)){ + visitInfo.setOutTime(endTime); + } + if(visitInfoMapper.updateById(visitInfo) <= 0){ + log.error("更新访客记录异常"); + } + } + + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java index 207b95c..b416f5c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dto.hik.PersonBatchDeleteRequest; import com.casic.missiles.modular.dto.hik.PersonSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.StaffInfo; import com.casic.missiles.modular.service.StaffInfoService; @@ -61,7 +62,7 @@ try { List pageList = staffInfoMapper.getStaffInfoListPage(page, staffInfoRequest); pageList.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); String base64 = Base64Util.transformPictureToBase64(uploadPath + staffInfo.getPicture()); staffInfo.setPicture(base64); }); @@ -104,6 +105,9 @@ log.error("请求海康,单个添加人员失败,海康response:{}", resultStr); return ResponseData.error("单个添加人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.insert(staffInfo) > 0){ return ResponseData.success(); } @@ -138,6 +142,9 @@ log.error("请求海康,单个修改人员失败,海康response:{}", resultStr); return ResponseData.error("单个修改人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.updateById(staffInfo) > 0){ return ResponseData.success(); } @@ -254,7 +261,7 @@ try { List list = staffInfoMapper.getStaffInfoList(staffInfoRequest); list.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); }); return list; } catch (DataAccessException ex) { diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java index 1b8ac75..8f47b37 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.casic.missiles.modular.dto.hik.FacePic; import com.casic.missiles.modular.dto.hik.FaceSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.BlackInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.BlackInfoService; @@ -52,7 +53,7 @@ try { List pageList = blackInfoMapper.getBlackInfoListPage(page, blackInfoRequest); pageList.forEach(blackInfo ->{ - blackInfo.setBlackReasonName(dictService.getDictNameByCode("blackReason", blackInfo.getBlackReason())); + blackInfo.setBlackReasonName(dictService.getDictNameByCode(SecurityEventDict.BLACK_REASON, blackInfo.getBlackReason())); }); return pageList; } catch (DataAccessException ex) { @@ -87,8 +88,8 @@ } JSONObject dataJson = (JSONObject)resultJson.get("data"); //设置海康人脸唯一标识、人脸分组唯一标识 - blackInfo.setIndexCode((String) dataJson.get("indexCode")); - blackInfo.setFaceGroupIndexCode((String) dataJson.get("faceGroupIndexCode")); + blackInfo.setIndexCode(String.valueOf(dataJson.get("indexCode"))); + blackInfo.setFaceGroupIndexCode(String.valueOf(dataJson.get("faceGroupIndexCode"))); //保存图片到本地 String picUrl = fileService.saveFile(blackInfo.getPicture()); blackInfo.setPicture(picUrl); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java index d1057e5..6fa536c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java @@ -7,6 +7,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.CaseInfoMapper; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.CaseInfoService; import lombok.extern.slf4j.Slf4j; @@ -45,10 +46,10 @@ try { List pageList = caseInfoMapper.getCaseInfoListPage(page, caseInfoRequest); pageList.forEach(caseInfo ->{ - caseInfo.setStatusName(dictService.getDictNameByCode("caseStatus", caseInfo.getStatus())); - caseInfo.setPositionName(dictService.getDictNameByCode("devicePosition", caseInfo.getPosition())); - caseInfo.setAreaName(dictService.getDictNameByCode("deviceArea", caseInfo.getArea())); - caseInfo.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", caseInfo.getIsKeyArea())); + caseInfo.setStatusName(dictService.getDictNameByCode(SecurityEventDict.CASE_STATUS, caseInfo.getStatus())); + caseInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, caseInfo.getPosition())); + caseInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, caseInfo.getArea())); + caseInfo.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, caseInfo.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -108,4 +109,9 @@ } return list; } + + @Override + public boolean insertCaseInfoBatch(List caseInfos) { + return this.saveBatch(caseInfos); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java index 849e4f1..9d9c731 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dao.GateGroupMapper; import com.casic.missiles.modular.dao.GroupDeviceMapper; import com.casic.missiles.modular.dto.*; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.DeviceRepairLog; import com.casic.missiles.modular.model.GateGroup; @@ -68,11 +69,11 @@ try { List pageList = deviceInfoMapper.getDeviceInfoListPage(page, deviceInfoRequest); pageList.forEach(device ->{ - device.setDevType(dictService.getDictNameByCode("deviceType", device.getDevType())); - device.setStatus(dictService.getDictNameByCode("deviceStatus", device.getStatus())); - device.setPositionName(dictService.getDictNameByCode("devicePosition", device.getPosition())); - device.setAreaName(dictService.getDictNameByCode("deviceArea", device.getArea())); - device.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", device.getIsKeyArea())); + device.setDevType(dictService.getDictNameByCode(SecurityEventDict.DEVICE_TYPE, device.getDevType())); + device.setStatus(dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, device.getStatus())); + device.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, device.getPosition())); + device.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, device.getArea())); + device.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, device.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -214,7 +215,7 @@ try { List pageList = gateGroupMapper.getGateGroupListPage(page, gateGroupRequest); pageList.forEach(gateGroup ->{ - gateGroup.setStatusName(dictService.getDictNameByCode("groupDeviceStatus", gateGroup.getStatus())); + gateGroup.setStatusName(dictService.getDictNameByCode(SecurityEventDict.GROUP_DEVICE_STATUS, gateGroup.getStatus())); }); return pageList; } catch (DataAccessException ex) { @@ -300,5 +301,11 @@ return deviceCodes; } + @Override + public List selectIndexCodesByCodes(List deviceCodes) { + List indexCodes = deviceInfoMapper.selectIndexCodesByCodes(deviceCodes); + return indexCodes; + } + } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java index 8a5f370..a95fff2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java @@ -8,6 +8,7 @@ import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.dao.FireEquipInfoMapper; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.FireEquipInfo; import com.casic.missiles.modular.service.FireEquipService; @@ -48,10 +49,10 @@ try { List pageList = fireEquipInfoMapper.getFireEquipInfoListPage(page, fireEquipRequest); pageList.forEach(equipInfo ->{ - equipInfo.setEquipTypeName(dictService.getDictNameByCode("equipType", equipInfo.getEquipType())); - equipInfo.setFireLevelName(dictService.getDictNameByCode("fireLevel", equipInfo.getFireLevel())); - equipInfo.setPositionName(dictService.getDictNameByCode("devicePosition", equipInfo.getPosition())); - equipInfo.setAreaName(dictService.getDictNameByCode("deviceArea", equipInfo.getArea())); + equipInfo.setEquipTypeName(dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, equipInfo.getEquipType())); + equipInfo.setFireLevelName(dictService.getDictNameByCode(SecurityEventDict.FIRE_LEVEL, equipInfo.getFireLevel())); + equipInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, equipInfo.getPosition())); + equipInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, equipInfo.getArea())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java new file mode 100644 index 0000000..b47f78f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java @@ -0,0 +1,284 @@ +package com.casic.missiles.modular.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.*; +import com.casic.missiles.modular.service.HikService; +import com.casic.missiles.modular.system.model.Dict; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +@Slf4j +@Service +public class HikServiceImpl implements HikService { + + @Resource + private AbstractDictService dictService; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Override + public CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public void propertyAttendanceHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 物业人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增物业人员考勤异常"); + return; + } + } + } + + @Override + public void securityPersonnelHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 安保人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增安保人员考勤异常"); + return; + } + } + } + + @Override + public void visitorRegisterHandler(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("startTime")); + String startTime = DateUtil.formatDateTime(parse); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + VisitInfo visitInfo = new VisitInfo(); + visitInfo.setVisitorName(data.getString("personName")); + visitInfo.setVisitorGender(data.getString("sex")); + visitInfo.setVisitorPhone(data.getString("phone")); + visitInfo.setInTime(startTime); //来访时间 +// visitInfo.setOutTime(); + if("111".equals(data.getString("idType"))){ + visitInfo.setInType("身份证"); + visitInfo.setIdCard(data.getString("idNo")); + } + visitInfo.setVisitReason(data.getString("purpose")); + visitInfo.setPicUri(data.getString("captureUrl")); + visitInfo.setServerIndexCode(data.getString("svrIndexCode")); + visitInfo.setVisitPosition(deviceInfo.getPosition()); + + if(visitInfoMapper.insert(visitInfo) <= 0){ + log.error("新增访客记录异常"); + } + } + + @Override + public void visitorCheckOutHandler(JSONObject event) { + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("endTime")); + String endTime = DateUtil.formatDateTime(parse); + VisitInfo visitInfo = visitInfoMapper.selectByOrderId(data.getString("visitorId")); + if(!Objects.isNull(visitInfo)){ + visitInfo.setOutTime(endTime); + } + if(visitInfoMapper.updateById(visitInfo) <= 0){ + log.error("更新访客记录异常"); + } + } + + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java index 207b95c..b416f5c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dto.hik.PersonBatchDeleteRequest; import com.casic.missiles.modular.dto.hik.PersonSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.StaffInfo; import com.casic.missiles.modular.service.StaffInfoService; @@ -61,7 +62,7 @@ try { List pageList = staffInfoMapper.getStaffInfoListPage(page, staffInfoRequest); pageList.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); String base64 = Base64Util.transformPictureToBase64(uploadPath + staffInfo.getPicture()); staffInfo.setPicture(base64); }); @@ -104,6 +105,9 @@ log.error("请求海康,单个添加人员失败,海康response:{}", resultStr); return ResponseData.error("单个添加人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.insert(staffInfo) > 0){ return ResponseData.success(); } @@ -138,6 +142,9 @@ log.error("请求海康,单个修改人员失败,海康response:{}", resultStr); return ResponseData.error("单个修改人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.updateById(staffInfo) > 0){ return ResponseData.success(); } @@ -254,7 +261,7 @@ try { List list = staffInfoMapper.getStaffInfoList(staffInfoRequest); list.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); }); return list; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java new file mode 100644 index 0000000..39618ea --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java @@ -0,0 +1,53 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +@Slf4j +@Service +public class VisitServiceImpl extends ServiceImpl implements VisitService { + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List visitInfoListPage(Page page, VisitorRequest visitorRequest) { + try { + List pageList = visitInfoMapper.getVisitInfoListPage(page, visitorRequest); + pageList.forEach(visitInfo ->{ + visitInfo.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitInfo.getVisitReason())); + visitInfo.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitInfo.getVisitPosition())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("访客: 查询分页出现异常,异常:{}", ex); + } + return null; + } + + @Override + public VisitInfo visitInfoDetail(String id) { + VisitInfo visitInfo = visitInfoMapper.selectById(id); + return visitInfo; + } +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java index 1b8ac75..8f47b37 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.casic.missiles.modular.dto.hik.FacePic; import com.casic.missiles.modular.dto.hik.FaceSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.BlackInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.BlackInfoService; @@ -52,7 +53,7 @@ try { List pageList = blackInfoMapper.getBlackInfoListPage(page, blackInfoRequest); pageList.forEach(blackInfo ->{ - blackInfo.setBlackReasonName(dictService.getDictNameByCode("blackReason", blackInfo.getBlackReason())); + blackInfo.setBlackReasonName(dictService.getDictNameByCode(SecurityEventDict.BLACK_REASON, blackInfo.getBlackReason())); }); return pageList; } catch (DataAccessException ex) { @@ -87,8 +88,8 @@ } JSONObject dataJson = (JSONObject)resultJson.get("data"); //设置海康人脸唯一标识、人脸分组唯一标识 - blackInfo.setIndexCode((String) dataJson.get("indexCode")); - blackInfo.setFaceGroupIndexCode((String) dataJson.get("faceGroupIndexCode")); + blackInfo.setIndexCode(String.valueOf(dataJson.get("indexCode"))); + blackInfo.setFaceGroupIndexCode(String.valueOf(dataJson.get("faceGroupIndexCode"))); //保存图片到本地 String picUrl = fileService.saveFile(blackInfo.getPicture()); blackInfo.setPicture(picUrl); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java index d1057e5..6fa536c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java @@ -7,6 +7,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.CaseInfoMapper; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.CaseInfoService; import lombok.extern.slf4j.Slf4j; @@ -45,10 +46,10 @@ try { List pageList = caseInfoMapper.getCaseInfoListPage(page, caseInfoRequest); pageList.forEach(caseInfo ->{ - caseInfo.setStatusName(dictService.getDictNameByCode("caseStatus", caseInfo.getStatus())); - caseInfo.setPositionName(dictService.getDictNameByCode("devicePosition", caseInfo.getPosition())); - caseInfo.setAreaName(dictService.getDictNameByCode("deviceArea", caseInfo.getArea())); - caseInfo.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", caseInfo.getIsKeyArea())); + caseInfo.setStatusName(dictService.getDictNameByCode(SecurityEventDict.CASE_STATUS, caseInfo.getStatus())); + caseInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, caseInfo.getPosition())); + caseInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, caseInfo.getArea())); + caseInfo.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, caseInfo.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -108,4 +109,9 @@ } return list; } + + @Override + public boolean insertCaseInfoBatch(List caseInfos) { + return this.saveBatch(caseInfos); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java index 849e4f1..9d9c731 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dao.GateGroupMapper; import com.casic.missiles.modular.dao.GroupDeviceMapper; import com.casic.missiles.modular.dto.*; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.DeviceRepairLog; import com.casic.missiles.modular.model.GateGroup; @@ -68,11 +69,11 @@ try { List pageList = deviceInfoMapper.getDeviceInfoListPage(page, deviceInfoRequest); pageList.forEach(device ->{ - device.setDevType(dictService.getDictNameByCode("deviceType", device.getDevType())); - device.setStatus(dictService.getDictNameByCode("deviceStatus", device.getStatus())); - device.setPositionName(dictService.getDictNameByCode("devicePosition", device.getPosition())); - device.setAreaName(dictService.getDictNameByCode("deviceArea", device.getArea())); - device.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", device.getIsKeyArea())); + device.setDevType(dictService.getDictNameByCode(SecurityEventDict.DEVICE_TYPE, device.getDevType())); + device.setStatus(dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, device.getStatus())); + device.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, device.getPosition())); + device.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, device.getArea())); + device.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, device.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -214,7 +215,7 @@ try { List pageList = gateGroupMapper.getGateGroupListPage(page, gateGroupRequest); pageList.forEach(gateGroup ->{ - gateGroup.setStatusName(dictService.getDictNameByCode("groupDeviceStatus", gateGroup.getStatus())); + gateGroup.setStatusName(dictService.getDictNameByCode(SecurityEventDict.GROUP_DEVICE_STATUS, gateGroup.getStatus())); }); return pageList; } catch (DataAccessException ex) { @@ -300,5 +301,11 @@ return deviceCodes; } + @Override + public List selectIndexCodesByCodes(List deviceCodes) { + List indexCodes = deviceInfoMapper.selectIndexCodesByCodes(deviceCodes); + return indexCodes; + } + } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java index 8a5f370..a95fff2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java @@ -8,6 +8,7 @@ import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.dao.FireEquipInfoMapper; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.FireEquipInfo; import com.casic.missiles.modular.service.FireEquipService; @@ -48,10 +49,10 @@ try { List pageList = fireEquipInfoMapper.getFireEquipInfoListPage(page, fireEquipRequest); pageList.forEach(equipInfo ->{ - equipInfo.setEquipTypeName(dictService.getDictNameByCode("equipType", equipInfo.getEquipType())); - equipInfo.setFireLevelName(dictService.getDictNameByCode("fireLevel", equipInfo.getFireLevel())); - equipInfo.setPositionName(dictService.getDictNameByCode("devicePosition", equipInfo.getPosition())); - equipInfo.setAreaName(dictService.getDictNameByCode("deviceArea", equipInfo.getArea())); + equipInfo.setEquipTypeName(dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, equipInfo.getEquipType())); + equipInfo.setFireLevelName(dictService.getDictNameByCode(SecurityEventDict.FIRE_LEVEL, equipInfo.getFireLevel())); + equipInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, equipInfo.getPosition())); + equipInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, equipInfo.getArea())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java new file mode 100644 index 0000000..b47f78f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java @@ -0,0 +1,284 @@ +package com.casic.missiles.modular.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.*; +import com.casic.missiles.modular.service.HikService; +import com.casic.missiles.modular.system.model.Dict; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +@Slf4j +@Service +public class HikServiceImpl implements HikService { + + @Resource + private AbstractDictService dictService; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Override + public CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public void propertyAttendanceHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 物业人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增物业人员考勤异常"); + return; + } + } + } + + @Override + public void securityPersonnelHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 安保人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增安保人员考勤异常"); + return; + } + } + } + + @Override + public void visitorRegisterHandler(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("startTime")); + String startTime = DateUtil.formatDateTime(parse); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + VisitInfo visitInfo = new VisitInfo(); + visitInfo.setVisitorName(data.getString("personName")); + visitInfo.setVisitorGender(data.getString("sex")); + visitInfo.setVisitorPhone(data.getString("phone")); + visitInfo.setInTime(startTime); //来访时间 +// visitInfo.setOutTime(); + if("111".equals(data.getString("idType"))){ + visitInfo.setInType("身份证"); + visitInfo.setIdCard(data.getString("idNo")); + } + visitInfo.setVisitReason(data.getString("purpose")); + visitInfo.setPicUri(data.getString("captureUrl")); + visitInfo.setServerIndexCode(data.getString("svrIndexCode")); + visitInfo.setVisitPosition(deviceInfo.getPosition()); + + if(visitInfoMapper.insert(visitInfo) <= 0){ + log.error("新增访客记录异常"); + } + } + + @Override + public void visitorCheckOutHandler(JSONObject event) { + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("endTime")); + String endTime = DateUtil.formatDateTime(parse); + VisitInfo visitInfo = visitInfoMapper.selectByOrderId(data.getString("visitorId")); + if(!Objects.isNull(visitInfo)){ + visitInfo.setOutTime(endTime); + } + if(visitInfoMapper.updateById(visitInfo) <= 0){ + log.error("更新访客记录异常"); + } + } + + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java index 207b95c..b416f5c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dto.hik.PersonBatchDeleteRequest; import com.casic.missiles.modular.dto.hik.PersonSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.StaffInfo; import com.casic.missiles.modular.service.StaffInfoService; @@ -61,7 +62,7 @@ try { List pageList = staffInfoMapper.getStaffInfoListPage(page, staffInfoRequest); pageList.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); String base64 = Base64Util.transformPictureToBase64(uploadPath + staffInfo.getPicture()); staffInfo.setPicture(base64); }); @@ -104,6 +105,9 @@ log.error("请求海康,单个添加人员失败,海康response:{}", resultStr); return ResponseData.error("单个添加人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.insert(staffInfo) > 0){ return ResponseData.success(); } @@ -138,6 +142,9 @@ log.error("请求海康,单个修改人员失败,海康response:{}", resultStr); return ResponseData.error("单个修改人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.updateById(staffInfo) > 0){ return ResponseData.success(); } @@ -254,7 +261,7 @@ try { List list = staffInfoMapper.getStaffInfoList(staffInfoRequest); list.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); }); return list; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java new file mode 100644 index 0000000..39618ea --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java @@ -0,0 +1,53 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +@Slf4j +@Service +public class VisitServiceImpl extends ServiceImpl implements VisitService { + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List visitInfoListPage(Page page, VisitorRequest visitorRequest) { + try { + List pageList = visitInfoMapper.getVisitInfoListPage(page, visitorRequest); + pageList.forEach(visitInfo ->{ + visitInfo.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitInfo.getVisitReason())); + visitInfo.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitInfo.getVisitPosition())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("访客: 查询分页出现异常,异常:{}", ex); + } + return null; + } + + @Override + public VisitInfo visitInfoDetail(String id) { + VisitInfo visitInfo = visitInfoMapper.selectById(id); + return visitInfo; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java index d9fa377..1f3f89b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java @@ -1,7 +1,9 @@ package com.casic.missiles.modular.service.impl; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -11,16 +13,27 @@ import com.casic.missiles.modular.dto.hik.AppointmentFreeRegisterRequest; import com.casic.missiles.modular.dto.hik.VisitorInfo; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.VisitorApply; import com.casic.missiles.modular.service.VisitorApplyService; import com.casic.missiles.modular.util.HikUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.validation.BeanPropertyBindingResult; +import org.springframework.validation.FieldError; +import org.springframework.validation.Validator; import javax.annotation.Resource; +import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * @Description: @@ -36,12 +49,16 @@ @Resource private AbstractDictService dictService; + @Resource + private Validator validator; + @Override public List visitorApplyListPage(Page page, VisitorApplyRequest visitorApplyRequest) { try { List pageList = visitorApplyMapper.getVisitorApplyListPage(page, visitorApplyRequest); pageList.forEach(visitorApply ->{ - visitorApply.setVisitReason(dictService.getDictNameByCode("visitReason", visitorApply.getVisitReason())); + visitorApply.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitorApply.getVisitReason())); + visitorApply.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitorApply.getVisitPosition())); }); return pageList; } catch (DataAccessException ex) { @@ -51,17 +68,17 @@ } @Override + @Transactional(rollbackFor = Exception.class) public int addVisitorApply(VisitorApply visitorApply) { - // TODO: 2022/7/26 数据重复处理 + //无需判重,可预约多个时间段 AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); - // TODO: 2022/7/25 ReceptionistId由前端传,数据源自海康,需考虑海康员工唯一标识与我们唯一标识对应问题 //将时间转换为海康ISO8601格式 DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); - - appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getReceptionistId()); + //海康员工唯一标识receptionistId就是我们录入的到海康的员工号 + appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getStaffCode()); appointmentFreeRegisterRequest.setPersonNum(1); appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); @@ -73,6 +90,7 @@ visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); visitorInfo.setCertificateNo(visitorApply.getIdCard()); visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); @@ -82,26 +100,191 @@ log.error("请求海康,预约免登记失败,海康response:{}", resultStr); return 0; } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); return visitorApplyMapper.insert(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int updateVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + //修改海康访客预约 + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setAppointRecordId(visitorApply1.getAppointRecordId()); + appointmentFreeRegisterRequest.setReceptionistId(visitorApply1.getStaffCode()); + DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(visitorApply.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(visitorApply.getVisitorName()); + visitorInfo.setGender(visitorApply.getVisitorGender()); + visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); + visitorInfo.setCertificateNo(visitorApply.getIdCard()); + visitorInfo.setCertificateType(111); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); + } + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + + String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_UPDATE, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,修改访客预约失败,海康response:{}", resultStr); + return 0; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); + } return visitorApplyMapper.updateById(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + if(StringUtils.isNotEmpty(visitorApply1.getAppointRecordId())){ + List appointRecordIds = new ArrayList<>(); + appointRecordIds.add(visitorApply.getAppointRecordId()); + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("该访客:{},未在海康进行预约成功,无法取消预约", visitorApply.getVisitorName()); + return 0; + } return visitorApplyMapper.deleteById(visitorApply.getId()); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteBatchVisitorApply(List ids) { + List visitorApplies = visitorApplyMapper.selectBatchIds(ids); + List appointRecordIds = visitorApplies.stream().map(VisitorApply::getAppointRecordId).collect(Collectors.toList()); + if(!CollectionUtils.isEmpty(appointRecordIds)){ + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,批量取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("访客列表:{},未在海康进行预约成功,无法取消预约", appointRecordIds); + return 0; + } return deleteBatchVisitorApply(ids); } @Override public List addVisitorApplyBatch(List results) { - return null; + BeanPropertyBindingResult beanPropertyBindingResult = new BeanPropertyBindingResult(CaseInfo.class, "访客申请导入校验"); + List list = new ArrayList<>(); + if (!CollectionUtil.isEmpty(results)) { + final Integer[] index = {0}; + List appointList = new ArrayList<>(); + results.forEach(busConcentrator -> { + validator.validate(busConcentrator, beanPropertyBindingResult); + index[0]++; + if (beanPropertyBindingResult.hasErrors()) { + List errors = beanPropertyBindingResult.getFieldErrors(); + errors.forEach(error -> { + list.add(" 第" + index[0] + "行,".concat(error.getDefaultMessage())); + return; + } + ); + return; + } + if (StrUtil.isNotEmpty(busConcentrator.getInTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getInTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + if (StrUtil.isNotEmpty(busConcentrator.getOutTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getOutTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + DateTime inTimeDate = DateUtil.parse(busConcentrator.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(busConcentrator.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setReceptionistId(busConcentrator.getStaffCode()); + appointmentFreeRegisterRequest.setPersonNum(1); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(busConcentrator.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(busConcentrator.getVisitorName()); + visitorInfo.setGender(busConcentrator.getVisitorGender()); + visitorInfo.setPhoneNo(busConcentrator.getVisitorPhone()); + visitorInfo.setCertificateNo(busConcentrator.getIdCard()); + visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(busConcentrator.getPicUri()); + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + appointList.add(appointmentFreeRegisterRequest); + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + appointList.forEach(app -> { + String body = JSONObject.toJSONString(app); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_FREE_REGISTER, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,预约免登记失败,海康response:{}", resultStr); + list.add("请求海康,预约免登记失败,访客姓名:"+app.getVisitorInfo().getVisitorName()); + return; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + for (VisitorApply result : results) { + //身份证判断同一访客,设置访客信息 + if(result.getIdCard().equals(app.getVisitorInfo().getCertificateNo())){ + result.setAppointRecordId(appointRecordId); + result.setOrderId(orderId); + result.setPicUri(picUri); + } + } + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + this.saveBatch(results); + } + return list; } } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java index 1b8ac75..8f47b37 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.casic.missiles.modular.dto.hik.FacePic; import com.casic.missiles.modular.dto.hik.FaceSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.BlackInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.BlackInfoService; @@ -52,7 +53,7 @@ try { List pageList = blackInfoMapper.getBlackInfoListPage(page, blackInfoRequest); pageList.forEach(blackInfo ->{ - blackInfo.setBlackReasonName(dictService.getDictNameByCode("blackReason", blackInfo.getBlackReason())); + blackInfo.setBlackReasonName(dictService.getDictNameByCode(SecurityEventDict.BLACK_REASON, blackInfo.getBlackReason())); }); return pageList; } catch (DataAccessException ex) { @@ -87,8 +88,8 @@ } JSONObject dataJson = (JSONObject)resultJson.get("data"); //设置海康人脸唯一标识、人脸分组唯一标识 - blackInfo.setIndexCode((String) dataJson.get("indexCode")); - blackInfo.setFaceGroupIndexCode((String) dataJson.get("faceGroupIndexCode")); + blackInfo.setIndexCode(String.valueOf(dataJson.get("indexCode"))); + blackInfo.setFaceGroupIndexCode(String.valueOf(dataJson.get("faceGroupIndexCode"))); //保存图片到本地 String picUrl = fileService.saveFile(blackInfo.getPicture()); blackInfo.setPicture(picUrl); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java index d1057e5..6fa536c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java @@ -7,6 +7,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.CaseInfoMapper; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.CaseInfoService; import lombok.extern.slf4j.Slf4j; @@ -45,10 +46,10 @@ try { List pageList = caseInfoMapper.getCaseInfoListPage(page, caseInfoRequest); pageList.forEach(caseInfo ->{ - caseInfo.setStatusName(dictService.getDictNameByCode("caseStatus", caseInfo.getStatus())); - caseInfo.setPositionName(dictService.getDictNameByCode("devicePosition", caseInfo.getPosition())); - caseInfo.setAreaName(dictService.getDictNameByCode("deviceArea", caseInfo.getArea())); - caseInfo.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", caseInfo.getIsKeyArea())); + caseInfo.setStatusName(dictService.getDictNameByCode(SecurityEventDict.CASE_STATUS, caseInfo.getStatus())); + caseInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, caseInfo.getPosition())); + caseInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, caseInfo.getArea())); + caseInfo.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, caseInfo.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -108,4 +109,9 @@ } return list; } + + @Override + public boolean insertCaseInfoBatch(List caseInfos) { + return this.saveBatch(caseInfos); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java index 849e4f1..9d9c731 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dao.GateGroupMapper; import com.casic.missiles.modular.dao.GroupDeviceMapper; import com.casic.missiles.modular.dto.*; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.DeviceRepairLog; import com.casic.missiles.modular.model.GateGroup; @@ -68,11 +69,11 @@ try { List pageList = deviceInfoMapper.getDeviceInfoListPage(page, deviceInfoRequest); pageList.forEach(device ->{ - device.setDevType(dictService.getDictNameByCode("deviceType", device.getDevType())); - device.setStatus(dictService.getDictNameByCode("deviceStatus", device.getStatus())); - device.setPositionName(dictService.getDictNameByCode("devicePosition", device.getPosition())); - device.setAreaName(dictService.getDictNameByCode("deviceArea", device.getArea())); - device.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", device.getIsKeyArea())); + device.setDevType(dictService.getDictNameByCode(SecurityEventDict.DEVICE_TYPE, device.getDevType())); + device.setStatus(dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, device.getStatus())); + device.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, device.getPosition())); + device.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, device.getArea())); + device.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, device.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -214,7 +215,7 @@ try { List pageList = gateGroupMapper.getGateGroupListPage(page, gateGroupRequest); pageList.forEach(gateGroup ->{ - gateGroup.setStatusName(dictService.getDictNameByCode("groupDeviceStatus", gateGroup.getStatus())); + gateGroup.setStatusName(dictService.getDictNameByCode(SecurityEventDict.GROUP_DEVICE_STATUS, gateGroup.getStatus())); }); return pageList; } catch (DataAccessException ex) { @@ -300,5 +301,11 @@ return deviceCodes; } + @Override + public List selectIndexCodesByCodes(List deviceCodes) { + List indexCodes = deviceInfoMapper.selectIndexCodesByCodes(deviceCodes); + return indexCodes; + } + } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java index 8a5f370..a95fff2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java @@ -8,6 +8,7 @@ import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.dao.FireEquipInfoMapper; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.FireEquipInfo; import com.casic.missiles.modular.service.FireEquipService; @@ -48,10 +49,10 @@ try { List pageList = fireEquipInfoMapper.getFireEquipInfoListPage(page, fireEquipRequest); pageList.forEach(equipInfo ->{ - equipInfo.setEquipTypeName(dictService.getDictNameByCode("equipType", equipInfo.getEquipType())); - equipInfo.setFireLevelName(dictService.getDictNameByCode("fireLevel", equipInfo.getFireLevel())); - equipInfo.setPositionName(dictService.getDictNameByCode("devicePosition", equipInfo.getPosition())); - equipInfo.setAreaName(dictService.getDictNameByCode("deviceArea", equipInfo.getArea())); + equipInfo.setEquipTypeName(dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, equipInfo.getEquipType())); + equipInfo.setFireLevelName(dictService.getDictNameByCode(SecurityEventDict.FIRE_LEVEL, equipInfo.getFireLevel())); + equipInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, equipInfo.getPosition())); + equipInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, equipInfo.getArea())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java new file mode 100644 index 0000000..b47f78f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java @@ -0,0 +1,284 @@ +package com.casic.missiles.modular.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.*; +import com.casic.missiles.modular.service.HikService; +import com.casic.missiles.modular.system.model.Dict; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +@Slf4j +@Service +public class HikServiceImpl implements HikService { + + @Resource + private AbstractDictService dictService; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Override + public CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public void propertyAttendanceHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 物业人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增物业人员考勤异常"); + return; + } + } + } + + @Override + public void securityPersonnelHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 安保人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增安保人员考勤异常"); + return; + } + } + } + + @Override + public void visitorRegisterHandler(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("startTime")); + String startTime = DateUtil.formatDateTime(parse); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + VisitInfo visitInfo = new VisitInfo(); + visitInfo.setVisitorName(data.getString("personName")); + visitInfo.setVisitorGender(data.getString("sex")); + visitInfo.setVisitorPhone(data.getString("phone")); + visitInfo.setInTime(startTime); //来访时间 +// visitInfo.setOutTime(); + if("111".equals(data.getString("idType"))){ + visitInfo.setInType("身份证"); + visitInfo.setIdCard(data.getString("idNo")); + } + visitInfo.setVisitReason(data.getString("purpose")); + visitInfo.setPicUri(data.getString("captureUrl")); + visitInfo.setServerIndexCode(data.getString("svrIndexCode")); + visitInfo.setVisitPosition(deviceInfo.getPosition()); + + if(visitInfoMapper.insert(visitInfo) <= 0){ + log.error("新增访客记录异常"); + } + } + + @Override + public void visitorCheckOutHandler(JSONObject event) { + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("endTime")); + String endTime = DateUtil.formatDateTime(parse); + VisitInfo visitInfo = visitInfoMapper.selectByOrderId(data.getString("visitorId")); + if(!Objects.isNull(visitInfo)){ + visitInfo.setOutTime(endTime); + } + if(visitInfoMapper.updateById(visitInfo) <= 0){ + log.error("更新访客记录异常"); + } + } + + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java index 207b95c..b416f5c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dto.hik.PersonBatchDeleteRequest; import com.casic.missiles.modular.dto.hik.PersonSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.StaffInfo; import com.casic.missiles.modular.service.StaffInfoService; @@ -61,7 +62,7 @@ try { List pageList = staffInfoMapper.getStaffInfoListPage(page, staffInfoRequest); pageList.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); String base64 = Base64Util.transformPictureToBase64(uploadPath + staffInfo.getPicture()); staffInfo.setPicture(base64); }); @@ -104,6 +105,9 @@ log.error("请求海康,单个添加人员失败,海康response:{}", resultStr); return ResponseData.error("单个添加人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.insert(staffInfo) > 0){ return ResponseData.success(); } @@ -138,6 +142,9 @@ log.error("请求海康,单个修改人员失败,海康response:{}", resultStr); return ResponseData.error("单个修改人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.updateById(staffInfo) > 0){ return ResponseData.success(); } @@ -254,7 +261,7 @@ try { List list = staffInfoMapper.getStaffInfoList(staffInfoRequest); list.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); }); return list; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java new file mode 100644 index 0000000..39618ea --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java @@ -0,0 +1,53 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +@Slf4j +@Service +public class VisitServiceImpl extends ServiceImpl implements VisitService { + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List visitInfoListPage(Page page, VisitorRequest visitorRequest) { + try { + List pageList = visitInfoMapper.getVisitInfoListPage(page, visitorRequest); + pageList.forEach(visitInfo ->{ + visitInfo.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitInfo.getVisitReason())); + visitInfo.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitInfo.getVisitPosition())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("访客: 查询分页出现异常,异常:{}", ex); + } + return null; + } + + @Override + public VisitInfo visitInfoDetail(String id) { + VisitInfo visitInfo = visitInfoMapper.selectById(id); + return visitInfo; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java index d9fa377..1f3f89b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java @@ -1,7 +1,9 @@ package com.casic.missiles.modular.service.impl; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -11,16 +13,27 @@ import com.casic.missiles.modular.dto.hik.AppointmentFreeRegisterRequest; import com.casic.missiles.modular.dto.hik.VisitorInfo; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.VisitorApply; import com.casic.missiles.modular.service.VisitorApplyService; import com.casic.missiles.modular.util.HikUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.validation.BeanPropertyBindingResult; +import org.springframework.validation.FieldError; +import org.springframework.validation.Validator; import javax.annotation.Resource; +import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * @Description: @@ -36,12 +49,16 @@ @Resource private AbstractDictService dictService; + @Resource + private Validator validator; + @Override public List visitorApplyListPage(Page page, VisitorApplyRequest visitorApplyRequest) { try { List pageList = visitorApplyMapper.getVisitorApplyListPage(page, visitorApplyRequest); pageList.forEach(visitorApply ->{ - visitorApply.setVisitReason(dictService.getDictNameByCode("visitReason", visitorApply.getVisitReason())); + visitorApply.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitorApply.getVisitReason())); + visitorApply.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitorApply.getVisitPosition())); }); return pageList; } catch (DataAccessException ex) { @@ -51,17 +68,17 @@ } @Override + @Transactional(rollbackFor = Exception.class) public int addVisitorApply(VisitorApply visitorApply) { - // TODO: 2022/7/26 数据重复处理 + //无需判重,可预约多个时间段 AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); - // TODO: 2022/7/25 ReceptionistId由前端传,数据源自海康,需考虑海康员工唯一标识与我们唯一标识对应问题 //将时间转换为海康ISO8601格式 DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); - - appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getReceptionistId()); + //海康员工唯一标识receptionistId就是我们录入的到海康的员工号 + appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getStaffCode()); appointmentFreeRegisterRequest.setPersonNum(1); appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); @@ -73,6 +90,7 @@ visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); visitorInfo.setCertificateNo(visitorApply.getIdCard()); visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); @@ -82,26 +100,191 @@ log.error("请求海康,预约免登记失败,海康response:{}", resultStr); return 0; } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); return visitorApplyMapper.insert(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int updateVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + //修改海康访客预约 + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setAppointRecordId(visitorApply1.getAppointRecordId()); + appointmentFreeRegisterRequest.setReceptionistId(visitorApply1.getStaffCode()); + DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(visitorApply.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(visitorApply.getVisitorName()); + visitorInfo.setGender(visitorApply.getVisitorGender()); + visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); + visitorInfo.setCertificateNo(visitorApply.getIdCard()); + visitorInfo.setCertificateType(111); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); + } + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + + String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_UPDATE, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,修改访客预约失败,海康response:{}", resultStr); + return 0; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); + } return visitorApplyMapper.updateById(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + if(StringUtils.isNotEmpty(visitorApply1.getAppointRecordId())){ + List appointRecordIds = new ArrayList<>(); + appointRecordIds.add(visitorApply.getAppointRecordId()); + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("该访客:{},未在海康进行预约成功,无法取消预约", visitorApply.getVisitorName()); + return 0; + } return visitorApplyMapper.deleteById(visitorApply.getId()); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteBatchVisitorApply(List ids) { + List visitorApplies = visitorApplyMapper.selectBatchIds(ids); + List appointRecordIds = visitorApplies.stream().map(VisitorApply::getAppointRecordId).collect(Collectors.toList()); + if(!CollectionUtils.isEmpty(appointRecordIds)){ + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,批量取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("访客列表:{},未在海康进行预约成功,无法取消预约", appointRecordIds); + return 0; + } return deleteBatchVisitorApply(ids); } @Override public List addVisitorApplyBatch(List results) { - return null; + BeanPropertyBindingResult beanPropertyBindingResult = new BeanPropertyBindingResult(CaseInfo.class, "访客申请导入校验"); + List list = new ArrayList<>(); + if (!CollectionUtil.isEmpty(results)) { + final Integer[] index = {0}; + List appointList = new ArrayList<>(); + results.forEach(busConcentrator -> { + validator.validate(busConcentrator, beanPropertyBindingResult); + index[0]++; + if (beanPropertyBindingResult.hasErrors()) { + List errors = beanPropertyBindingResult.getFieldErrors(); + errors.forEach(error -> { + list.add(" 第" + index[0] + "行,".concat(error.getDefaultMessage())); + return; + } + ); + return; + } + if (StrUtil.isNotEmpty(busConcentrator.getInTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getInTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + if (StrUtil.isNotEmpty(busConcentrator.getOutTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getOutTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + DateTime inTimeDate = DateUtil.parse(busConcentrator.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(busConcentrator.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setReceptionistId(busConcentrator.getStaffCode()); + appointmentFreeRegisterRequest.setPersonNum(1); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(busConcentrator.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(busConcentrator.getVisitorName()); + visitorInfo.setGender(busConcentrator.getVisitorGender()); + visitorInfo.setPhoneNo(busConcentrator.getVisitorPhone()); + visitorInfo.setCertificateNo(busConcentrator.getIdCard()); + visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(busConcentrator.getPicUri()); + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + appointList.add(appointmentFreeRegisterRequest); + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + appointList.forEach(app -> { + String body = JSONObject.toJSONString(app); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_FREE_REGISTER, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,预约免登记失败,海康response:{}", resultStr); + list.add("请求海康,预约免登记失败,访客姓名:"+app.getVisitorInfo().getVisitorName()); + return; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + for (VisitorApply result : results) { + //身份证判断同一访客,设置访客信息 + if(result.getIdCard().equals(app.getVisitorInfo().getCertificateNo())){ + result.setAppointRecordId(appointRecordId); + result.setOrderId(orderId); + result.setPicUri(picUri); + } + } + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + this.saveBatch(results); + } + return list; } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java new file mode 100644 index 0000000..511f014 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java @@ -0,0 +1,24 @@ +package com.casic.missiles.modular.util; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 11:09 + */ +@Slf4j +@Component +public class ThreadPoolUtil { + public static ExecutorService executorService; + + @PostConstruct + public void initExecutorService() { + executorService = Executors.newFixedThreadPool(10); + } +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java index 1b8ac75..8f47b37 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.casic.missiles.modular.dto.hik.FacePic; import com.casic.missiles.modular.dto.hik.FaceSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.BlackInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.BlackInfoService; @@ -52,7 +53,7 @@ try { List pageList = blackInfoMapper.getBlackInfoListPage(page, blackInfoRequest); pageList.forEach(blackInfo ->{ - blackInfo.setBlackReasonName(dictService.getDictNameByCode("blackReason", blackInfo.getBlackReason())); + blackInfo.setBlackReasonName(dictService.getDictNameByCode(SecurityEventDict.BLACK_REASON, blackInfo.getBlackReason())); }); return pageList; } catch (DataAccessException ex) { @@ -87,8 +88,8 @@ } JSONObject dataJson = (JSONObject)resultJson.get("data"); //设置海康人脸唯一标识、人脸分组唯一标识 - blackInfo.setIndexCode((String) dataJson.get("indexCode")); - blackInfo.setFaceGroupIndexCode((String) dataJson.get("faceGroupIndexCode")); + blackInfo.setIndexCode(String.valueOf(dataJson.get("indexCode"))); + blackInfo.setFaceGroupIndexCode(String.valueOf(dataJson.get("faceGroupIndexCode"))); //保存图片到本地 String picUrl = fileService.saveFile(blackInfo.getPicture()); blackInfo.setPicture(picUrl); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java index d1057e5..6fa536c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java @@ -7,6 +7,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.CaseInfoMapper; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.CaseInfoService; import lombok.extern.slf4j.Slf4j; @@ -45,10 +46,10 @@ try { List pageList = caseInfoMapper.getCaseInfoListPage(page, caseInfoRequest); pageList.forEach(caseInfo ->{ - caseInfo.setStatusName(dictService.getDictNameByCode("caseStatus", caseInfo.getStatus())); - caseInfo.setPositionName(dictService.getDictNameByCode("devicePosition", caseInfo.getPosition())); - caseInfo.setAreaName(dictService.getDictNameByCode("deviceArea", caseInfo.getArea())); - caseInfo.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", caseInfo.getIsKeyArea())); + caseInfo.setStatusName(dictService.getDictNameByCode(SecurityEventDict.CASE_STATUS, caseInfo.getStatus())); + caseInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, caseInfo.getPosition())); + caseInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, caseInfo.getArea())); + caseInfo.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, caseInfo.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -108,4 +109,9 @@ } return list; } + + @Override + public boolean insertCaseInfoBatch(List caseInfos) { + return this.saveBatch(caseInfos); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java index 849e4f1..9d9c731 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dao.GateGroupMapper; import com.casic.missiles.modular.dao.GroupDeviceMapper; import com.casic.missiles.modular.dto.*; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.DeviceRepairLog; import com.casic.missiles.modular.model.GateGroup; @@ -68,11 +69,11 @@ try { List pageList = deviceInfoMapper.getDeviceInfoListPage(page, deviceInfoRequest); pageList.forEach(device ->{ - device.setDevType(dictService.getDictNameByCode("deviceType", device.getDevType())); - device.setStatus(dictService.getDictNameByCode("deviceStatus", device.getStatus())); - device.setPositionName(dictService.getDictNameByCode("devicePosition", device.getPosition())); - device.setAreaName(dictService.getDictNameByCode("deviceArea", device.getArea())); - device.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", device.getIsKeyArea())); + device.setDevType(dictService.getDictNameByCode(SecurityEventDict.DEVICE_TYPE, device.getDevType())); + device.setStatus(dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, device.getStatus())); + device.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, device.getPosition())); + device.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, device.getArea())); + device.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, device.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -214,7 +215,7 @@ try { List pageList = gateGroupMapper.getGateGroupListPage(page, gateGroupRequest); pageList.forEach(gateGroup ->{ - gateGroup.setStatusName(dictService.getDictNameByCode("groupDeviceStatus", gateGroup.getStatus())); + gateGroup.setStatusName(dictService.getDictNameByCode(SecurityEventDict.GROUP_DEVICE_STATUS, gateGroup.getStatus())); }); return pageList; } catch (DataAccessException ex) { @@ -300,5 +301,11 @@ return deviceCodes; } + @Override + public List selectIndexCodesByCodes(List deviceCodes) { + List indexCodes = deviceInfoMapper.selectIndexCodesByCodes(deviceCodes); + return indexCodes; + } + } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java index 8a5f370..a95fff2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java @@ -8,6 +8,7 @@ import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.dao.FireEquipInfoMapper; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.FireEquipInfo; import com.casic.missiles.modular.service.FireEquipService; @@ -48,10 +49,10 @@ try { List pageList = fireEquipInfoMapper.getFireEquipInfoListPage(page, fireEquipRequest); pageList.forEach(equipInfo ->{ - equipInfo.setEquipTypeName(dictService.getDictNameByCode("equipType", equipInfo.getEquipType())); - equipInfo.setFireLevelName(dictService.getDictNameByCode("fireLevel", equipInfo.getFireLevel())); - equipInfo.setPositionName(dictService.getDictNameByCode("devicePosition", equipInfo.getPosition())); - equipInfo.setAreaName(dictService.getDictNameByCode("deviceArea", equipInfo.getArea())); + equipInfo.setEquipTypeName(dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, equipInfo.getEquipType())); + equipInfo.setFireLevelName(dictService.getDictNameByCode(SecurityEventDict.FIRE_LEVEL, equipInfo.getFireLevel())); + equipInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, equipInfo.getPosition())); + equipInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, equipInfo.getArea())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java new file mode 100644 index 0000000..b47f78f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java @@ -0,0 +1,284 @@ +package com.casic.missiles.modular.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.*; +import com.casic.missiles.modular.service.HikService; +import com.casic.missiles.modular.system.model.Dict; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +@Slf4j +@Service +public class HikServiceImpl implements HikService { + + @Resource + private AbstractDictService dictService; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Override + public CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public void propertyAttendanceHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 物业人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增物业人员考勤异常"); + return; + } + } + } + + @Override + public void securityPersonnelHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 安保人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增安保人员考勤异常"); + return; + } + } + } + + @Override + public void visitorRegisterHandler(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("startTime")); + String startTime = DateUtil.formatDateTime(parse); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + VisitInfo visitInfo = new VisitInfo(); + visitInfo.setVisitorName(data.getString("personName")); + visitInfo.setVisitorGender(data.getString("sex")); + visitInfo.setVisitorPhone(data.getString("phone")); + visitInfo.setInTime(startTime); //来访时间 +// visitInfo.setOutTime(); + if("111".equals(data.getString("idType"))){ + visitInfo.setInType("身份证"); + visitInfo.setIdCard(data.getString("idNo")); + } + visitInfo.setVisitReason(data.getString("purpose")); + visitInfo.setPicUri(data.getString("captureUrl")); + visitInfo.setServerIndexCode(data.getString("svrIndexCode")); + visitInfo.setVisitPosition(deviceInfo.getPosition()); + + if(visitInfoMapper.insert(visitInfo) <= 0){ + log.error("新增访客记录异常"); + } + } + + @Override + public void visitorCheckOutHandler(JSONObject event) { + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("endTime")); + String endTime = DateUtil.formatDateTime(parse); + VisitInfo visitInfo = visitInfoMapper.selectByOrderId(data.getString("visitorId")); + if(!Objects.isNull(visitInfo)){ + visitInfo.setOutTime(endTime); + } + if(visitInfoMapper.updateById(visitInfo) <= 0){ + log.error("更新访客记录异常"); + } + } + + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java index 207b95c..b416f5c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dto.hik.PersonBatchDeleteRequest; import com.casic.missiles.modular.dto.hik.PersonSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.StaffInfo; import com.casic.missiles.modular.service.StaffInfoService; @@ -61,7 +62,7 @@ try { List pageList = staffInfoMapper.getStaffInfoListPage(page, staffInfoRequest); pageList.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); String base64 = Base64Util.transformPictureToBase64(uploadPath + staffInfo.getPicture()); staffInfo.setPicture(base64); }); @@ -104,6 +105,9 @@ log.error("请求海康,单个添加人员失败,海康response:{}", resultStr); return ResponseData.error("单个添加人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.insert(staffInfo) > 0){ return ResponseData.success(); } @@ -138,6 +142,9 @@ log.error("请求海康,单个修改人员失败,海康response:{}", resultStr); return ResponseData.error("单个修改人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.updateById(staffInfo) > 0){ return ResponseData.success(); } @@ -254,7 +261,7 @@ try { List list = staffInfoMapper.getStaffInfoList(staffInfoRequest); list.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); }); return list; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java new file mode 100644 index 0000000..39618ea --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java @@ -0,0 +1,53 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +@Slf4j +@Service +public class VisitServiceImpl extends ServiceImpl implements VisitService { + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List visitInfoListPage(Page page, VisitorRequest visitorRequest) { + try { + List pageList = visitInfoMapper.getVisitInfoListPage(page, visitorRequest); + pageList.forEach(visitInfo ->{ + visitInfo.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitInfo.getVisitReason())); + visitInfo.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitInfo.getVisitPosition())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("访客: 查询分页出现异常,异常:{}", ex); + } + return null; + } + + @Override + public VisitInfo visitInfoDetail(String id) { + VisitInfo visitInfo = visitInfoMapper.selectById(id); + return visitInfo; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java index d9fa377..1f3f89b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java @@ -1,7 +1,9 @@ package com.casic.missiles.modular.service.impl; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -11,16 +13,27 @@ import com.casic.missiles.modular.dto.hik.AppointmentFreeRegisterRequest; import com.casic.missiles.modular.dto.hik.VisitorInfo; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.VisitorApply; import com.casic.missiles.modular.service.VisitorApplyService; import com.casic.missiles.modular.util.HikUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.validation.BeanPropertyBindingResult; +import org.springframework.validation.FieldError; +import org.springframework.validation.Validator; import javax.annotation.Resource; +import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * @Description: @@ -36,12 +49,16 @@ @Resource private AbstractDictService dictService; + @Resource + private Validator validator; + @Override public List visitorApplyListPage(Page page, VisitorApplyRequest visitorApplyRequest) { try { List pageList = visitorApplyMapper.getVisitorApplyListPage(page, visitorApplyRequest); pageList.forEach(visitorApply ->{ - visitorApply.setVisitReason(dictService.getDictNameByCode("visitReason", visitorApply.getVisitReason())); + visitorApply.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitorApply.getVisitReason())); + visitorApply.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitorApply.getVisitPosition())); }); return pageList; } catch (DataAccessException ex) { @@ -51,17 +68,17 @@ } @Override + @Transactional(rollbackFor = Exception.class) public int addVisitorApply(VisitorApply visitorApply) { - // TODO: 2022/7/26 数据重复处理 + //无需判重,可预约多个时间段 AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); - // TODO: 2022/7/25 ReceptionistId由前端传,数据源自海康,需考虑海康员工唯一标识与我们唯一标识对应问题 //将时间转换为海康ISO8601格式 DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); - - appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getReceptionistId()); + //海康员工唯一标识receptionistId就是我们录入的到海康的员工号 + appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getStaffCode()); appointmentFreeRegisterRequest.setPersonNum(1); appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); @@ -73,6 +90,7 @@ visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); visitorInfo.setCertificateNo(visitorApply.getIdCard()); visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); @@ -82,26 +100,191 @@ log.error("请求海康,预约免登记失败,海康response:{}", resultStr); return 0; } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); return visitorApplyMapper.insert(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int updateVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + //修改海康访客预约 + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setAppointRecordId(visitorApply1.getAppointRecordId()); + appointmentFreeRegisterRequest.setReceptionistId(visitorApply1.getStaffCode()); + DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(visitorApply.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(visitorApply.getVisitorName()); + visitorInfo.setGender(visitorApply.getVisitorGender()); + visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); + visitorInfo.setCertificateNo(visitorApply.getIdCard()); + visitorInfo.setCertificateType(111); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); + } + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + + String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_UPDATE, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,修改访客预约失败,海康response:{}", resultStr); + return 0; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); + } return visitorApplyMapper.updateById(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + if(StringUtils.isNotEmpty(visitorApply1.getAppointRecordId())){ + List appointRecordIds = new ArrayList<>(); + appointRecordIds.add(visitorApply.getAppointRecordId()); + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("该访客:{},未在海康进行预约成功,无法取消预约", visitorApply.getVisitorName()); + return 0; + } return visitorApplyMapper.deleteById(visitorApply.getId()); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteBatchVisitorApply(List ids) { + List visitorApplies = visitorApplyMapper.selectBatchIds(ids); + List appointRecordIds = visitorApplies.stream().map(VisitorApply::getAppointRecordId).collect(Collectors.toList()); + if(!CollectionUtils.isEmpty(appointRecordIds)){ + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,批量取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("访客列表:{},未在海康进行预约成功,无法取消预约", appointRecordIds); + return 0; + } return deleteBatchVisitorApply(ids); } @Override public List addVisitorApplyBatch(List results) { - return null; + BeanPropertyBindingResult beanPropertyBindingResult = new BeanPropertyBindingResult(CaseInfo.class, "访客申请导入校验"); + List list = new ArrayList<>(); + if (!CollectionUtil.isEmpty(results)) { + final Integer[] index = {0}; + List appointList = new ArrayList<>(); + results.forEach(busConcentrator -> { + validator.validate(busConcentrator, beanPropertyBindingResult); + index[0]++; + if (beanPropertyBindingResult.hasErrors()) { + List errors = beanPropertyBindingResult.getFieldErrors(); + errors.forEach(error -> { + list.add(" 第" + index[0] + "行,".concat(error.getDefaultMessage())); + return; + } + ); + return; + } + if (StrUtil.isNotEmpty(busConcentrator.getInTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getInTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + if (StrUtil.isNotEmpty(busConcentrator.getOutTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getOutTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + DateTime inTimeDate = DateUtil.parse(busConcentrator.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(busConcentrator.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setReceptionistId(busConcentrator.getStaffCode()); + appointmentFreeRegisterRequest.setPersonNum(1); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(busConcentrator.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(busConcentrator.getVisitorName()); + visitorInfo.setGender(busConcentrator.getVisitorGender()); + visitorInfo.setPhoneNo(busConcentrator.getVisitorPhone()); + visitorInfo.setCertificateNo(busConcentrator.getIdCard()); + visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(busConcentrator.getPicUri()); + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + appointList.add(appointmentFreeRegisterRequest); + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + appointList.forEach(app -> { + String body = JSONObject.toJSONString(app); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_FREE_REGISTER, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,预约免登记失败,海康response:{}", resultStr); + list.add("请求海康,预约免登记失败,访客姓名:"+app.getVisitorInfo().getVisitorName()); + return; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + for (VisitorApply result : results) { + //身份证判断同一访客,设置访客信息 + if(result.getIdCard().equals(app.getVisitorInfo().getCertificateNo())){ + result.setAppointRecordId(appointRecordId); + result.setOrderId(orderId); + result.setPicUri(picUri); + } + } + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + this.saveBatch(results); + } + return list; } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java new file mode 100644 index 0000000..511f014 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java @@ -0,0 +1,24 @@ +package com.casic.missiles.modular.util; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 11:09 + */ +@Slf4j +@Component +public class ThreadPoolUtil { + public static ExecutorService executorService; + + @PostConstruct + public void initExecutorService() { + executorService = Executors.newFixedThreadPool(10); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java b/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java index 9b4155c..5c7f422 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java @@ -1,5 +1,6 @@ package com.casic.missiles.modular.util; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.websocket.OnClose; @@ -18,6 +19,7 @@ * @Author: wangpeng * @Date: 2022/7/17 11:48 */ +@Slf4j @Component @ServerEndpoint("/websocket/{userId}") public class WebSocket { @@ -31,27 +33,32 @@ this.session = session; webSockets.add(this); sessionPool.put(userId, session); - System.out.println(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); + log.info(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); +// System.out.println(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); } @OnClose public void onClose() { webSockets.remove(this); - System.out.println("【websocket消息】连接断开,总数为:" + webSockets.size()); + log.info("【websocket消息】连接断开,总数为:" + webSockets.size()); +// System.out.println("【websocket消息】连接断开,总数为:" + webSockets.size()); } @OnMessage public void onMessage(String message) { - System.out.println("【websocket消息】收到客户端消息:" + message); + log.info("【websocket消息】收到客户端消息:" + message); +// System.out.println("【websocket消息】收到客户端消息:" + message); } // 此为广播消息 public void sendAllMessage(String message) { for (WebSocket webSocket : webSockets) { - System.out.println("【websocket消息】广播消息:" + message); + log.info("【websocket消息】广播消息:" + message); +// System.out.println("【websocket消息】广播消息:" + message); try { webSocket.session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】广播消息发送异常"); e.printStackTrace(); } } @@ -59,44 +66,31 @@ // 发送列表消息 public void sendListMessage(List userIds, String message) { - System.out.println("【websocket消息】列表消息:" + message); + log.info("【websocket消息】列表消息:" + message); +// System.out.println("【websocket消息】列表消息:" + message); for (String userId : userIds) { Session session = sessionPool.get(userId); if (session != null) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】列表消息发送异常"); e.printStackTrace(); } } } } - // 发送列表消息 - -// public void sendListMessage(List userIds, Object data){ -// System.out.println("【websocket消息】列表消息:"+data); -// for (String userId : userIds) { -// Session session = sessionPool.get(userId); -// if (session != null) { -// try { -//// session.getAsyncRemote().sendText(message); -// session.getAsyncRemote().sendObject(data); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } -// } -// } - // 此为单点消息 public void sendOneMessage(String userId, String message) { - System.out.println("【websocket消息】单点消息:" + message); + log.info("【websocket消息】单点消息:" + message); +// System.out.println("【websocket消息】单点消息:" + message); Session session = sessionPool.get(userId); if (session != null) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】单点消息发送异常"); e.printStackTrace(); } } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java index 1b8ac75..8f47b37 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.casic.missiles.modular.dto.hik.FacePic; import com.casic.missiles.modular.dto.hik.FaceSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.BlackInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.BlackInfoService; @@ -52,7 +53,7 @@ try { List pageList = blackInfoMapper.getBlackInfoListPage(page, blackInfoRequest); pageList.forEach(blackInfo ->{ - blackInfo.setBlackReasonName(dictService.getDictNameByCode("blackReason", blackInfo.getBlackReason())); + blackInfo.setBlackReasonName(dictService.getDictNameByCode(SecurityEventDict.BLACK_REASON, blackInfo.getBlackReason())); }); return pageList; } catch (DataAccessException ex) { @@ -87,8 +88,8 @@ } JSONObject dataJson = (JSONObject)resultJson.get("data"); //设置海康人脸唯一标识、人脸分组唯一标识 - blackInfo.setIndexCode((String) dataJson.get("indexCode")); - blackInfo.setFaceGroupIndexCode((String) dataJson.get("faceGroupIndexCode")); + blackInfo.setIndexCode(String.valueOf(dataJson.get("indexCode"))); + blackInfo.setFaceGroupIndexCode(String.valueOf(dataJson.get("faceGroupIndexCode"))); //保存图片到本地 String picUrl = fileService.saveFile(blackInfo.getPicture()); blackInfo.setPicture(picUrl); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java index d1057e5..6fa536c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java @@ -7,6 +7,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.CaseInfoMapper; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.CaseInfoService; import lombok.extern.slf4j.Slf4j; @@ -45,10 +46,10 @@ try { List pageList = caseInfoMapper.getCaseInfoListPage(page, caseInfoRequest); pageList.forEach(caseInfo ->{ - caseInfo.setStatusName(dictService.getDictNameByCode("caseStatus", caseInfo.getStatus())); - caseInfo.setPositionName(dictService.getDictNameByCode("devicePosition", caseInfo.getPosition())); - caseInfo.setAreaName(dictService.getDictNameByCode("deviceArea", caseInfo.getArea())); - caseInfo.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", caseInfo.getIsKeyArea())); + caseInfo.setStatusName(dictService.getDictNameByCode(SecurityEventDict.CASE_STATUS, caseInfo.getStatus())); + caseInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, caseInfo.getPosition())); + caseInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, caseInfo.getArea())); + caseInfo.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, caseInfo.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -108,4 +109,9 @@ } return list; } + + @Override + public boolean insertCaseInfoBatch(List caseInfos) { + return this.saveBatch(caseInfos); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java index 849e4f1..9d9c731 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dao.GateGroupMapper; import com.casic.missiles.modular.dao.GroupDeviceMapper; import com.casic.missiles.modular.dto.*; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.DeviceRepairLog; import com.casic.missiles.modular.model.GateGroup; @@ -68,11 +69,11 @@ try { List pageList = deviceInfoMapper.getDeviceInfoListPage(page, deviceInfoRequest); pageList.forEach(device ->{ - device.setDevType(dictService.getDictNameByCode("deviceType", device.getDevType())); - device.setStatus(dictService.getDictNameByCode("deviceStatus", device.getStatus())); - device.setPositionName(dictService.getDictNameByCode("devicePosition", device.getPosition())); - device.setAreaName(dictService.getDictNameByCode("deviceArea", device.getArea())); - device.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", device.getIsKeyArea())); + device.setDevType(dictService.getDictNameByCode(SecurityEventDict.DEVICE_TYPE, device.getDevType())); + device.setStatus(dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, device.getStatus())); + device.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, device.getPosition())); + device.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, device.getArea())); + device.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, device.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -214,7 +215,7 @@ try { List pageList = gateGroupMapper.getGateGroupListPage(page, gateGroupRequest); pageList.forEach(gateGroup ->{ - gateGroup.setStatusName(dictService.getDictNameByCode("groupDeviceStatus", gateGroup.getStatus())); + gateGroup.setStatusName(dictService.getDictNameByCode(SecurityEventDict.GROUP_DEVICE_STATUS, gateGroup.getStatus())); }); return pageList; } catch (DataAccessException ex) { @@ -300,5 +301,11 @@ return deviceCodes; } + @Override + public List selectIndexCodesByCodes(List deviceCodes) { + List indexCodes = deviceInfoMapper.selectIndexCodesByCodes(deviceCodes); + return indexCodes; + } + } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java index 8a5f370..a95fff2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java @@ -8,6 +8,7 @@ import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.dao.FireEquipInfoMapper; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.FireEquipInfo; import com.casic.missiles.modular.service.FireEquipService; @@ -48,10 +49,10 @@ try { List pageList = fireEquipInfoMapper.getFireEquipInfoListPage(page, fireEquipRequest); pageList.forEach(equipInfo ->{ - equipInfo.setEquipTypeName(dictService.getDictNameByCode("equipType", equipInfo.getEquipType())); - equipInfo.setFireLevelName(dictService.getDictNameByCode("fireLevel", equipInfo.getFireLevel())); - equipInfo.setPositionName(dictService.getDictNameByCode("devicePosition", equipInfo.getPosition())); - equipInfo.setAreaName(dictService.getDictNameByCode("deviceArea", equipInfo.getArea())); + equipInfo.setEquipTypeName(dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, equipInfo.getEquipType())); + equipInfo.setFireLevelName(dictService.getDictNameByCode(SecurityEventDict.FIRE_LEVEL, equipInfo.getFireLevel())); + equipInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, equipInfo.getPosition())); + equipInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, equipInfo.getArea())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java new file mode 100644 index 0000000..b47f78f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java @@ -0,0 +1,284 @@ +package com.casic.missiles.modular.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.*; +import com.casic.missiles.modular.service.HikService; +import com.casic.missiles.modular.system.model.Dict; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +@Slf4j +@Service +public class HikServiceImpl implements HikService { + + @Resource + private AbstractDictService dictService; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Override + public CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public void propertyAttendanceHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 物业人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增物业人员考勤异常"); + return; + } + } + } + + @Override + public void securityPersonnelHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 安保人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增安保人员考勤异常"); + return; + } + } + } + + @Override + public void visitorRegisterHandler(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("startTime")); + String startTime = DateUtil.formatDateTime(parse); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + VisitInfo visitInfo = new VisitInfo(); + visitInfo.setVisitorName(data.getString("personName")); + visitInfo.setVisitorGender(data.getString("sex")); + visitInfo.setVisitorPhone(data.getString("phone")); + visitInfo.setInTime(startTime); //来访时间 +// visitInfo.setOutTime(); + if("111".equals(data.getString("idType"))){ + visitInfo.setInType("身份证"); + visitInfo.setIdCard(data.getString("idNo")); + } + visitInfo.setVisitReason(data.getString("purpose")); + visitInfo.setPicUri(data.getString("captureUrl")); + visitInfo.setServerIndexCode(data.getString("svrIndexCode")); + visitInfo.setVisitPosition(deviceInfo.getPosition()); + + if(visitInfoMapper.insert(visitInfo) <= 0){ + log.error("新增访客记录异常"); + } + } + + @Override + public void visitorCheckOutHandler(JSONObject event) { + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("endTime")); + String endTime = DateUtil.formatDateTime(parse); + VisitInfo visitInfo = visitInfoMapper.selectByOrderId(data.getString("visitorId")); + if(!Objects.isNull(visitInfo)){ + visitInfo.setOutTime(endTime); + } + if(visitInfoMapper.updateById(visitInfo) <= 0){ + log.error("更新访客记录异常"); + } + } + + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java index 207b95c..b416f5c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dto.hik.PersonBatchDeleteRequest; import com.casic.missiles.modular.dto.hik.PersonSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.StaffInfo; import com.casic.missiles.modular.service.StaffInfoService; @@ -61,7 +62,7 @@ try { List pageList = staffInfoMapper.getStaffInfoListPage(page, staffInfoRequest); pageList.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); String base64 = Base64Util.transformPictureToBase64(uploadPath + staffInfo.getPicture()); staffInfo.setPicture(base64); }); @@ -104,6 +105,9 @@ log.error("请求海康,单个添加人员失败,海康response:{}", resultStr); return ResponseData.error("单个添加人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.insert(staffInfo) > 0){ return ResponseData.success(); } @@ -138,6 +142,9 @@ log.error("请求海康,单个修改人员失败,海康response:{}", resultStr); return ResponseData.error("单个修改人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.updateById(staffInfo) > 0){ return ResponseData.success(); } @@ -254,7 +261,7 @@ try { List list = staffInfoMapper.getStaffInfoList(staffInfoRequest); list.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); }); return list; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java new file mode 100644 index 0000000..39618ea --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java @@ -0,0 +1,53 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +@Slf4j +@Service +public class VisitServiceImpl extends ServiceImpl implements VisitService { + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List visitInfoListPage(Page page, VisitorRequest visitorRequest) { + try { + List pageList = visitInfoMapper.getVisitInfoListPage(page, visitorRequest); + pageList.forEach(visitInfo ->{ + visitInfo.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitInfo.getVisitReason())); + visitInfo.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitInfo.getVisitPosition())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("访客: 查询分页出现异常,异常:{}", ex); + } + return null; + } + + @Override + public VisitInfo visitInfoDetail(String id) { + VisitInfo visitInfo = visitInfoMapper.selectById(id); + return visitInfo; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java index d9fa377..1f3f89b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java @@ -1,7 +1,9 @@ package com.casic.missiles.modular.service.impl; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -11,16 +13,27 @@ import com.casic.missiles.modular.dto.hik.AppointmentFreeRegisterRequest; import com.casic.missiles.modular.dto.hik.VisitorInfo; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.VisitorApply; import com.casic.missiles.modular.service.VisitorApplyService; import com.casic.missiles.modular.util.HikUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.validation.BeanPropertyBindingResult; +import org.springframework.validation.FieldError; +import org.springframework.validation.Validator; import javax.annotation.Resource; +import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * @Description: @@ -36,12 +49,16 @@ @Resource private AbstractDictService dictService; + @Resource + private Validator validator; + @Override public List visitorApplyListPage(Page page, VisitorApplyRequest visitorApplyRequest) { try { List pageList = visitorApplyMapper.getVisitorApplyListPage(page, visitorApplyRequest); pageList.forEach(visitorApply ->{ - visitorApply.setVisitReason(dictService.getDictNameByCode("visitReason", visitorApply.getVisitReason())); + visitorApply.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitorApply.getVisitReason())); + visitorApply.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitorApply.getVisitPosition())); }); return pageList; } catch (DataAccessException ex) { @@ -51,17 +68,17 @@ } @Override + @Transactional(rollbackFor = Exception.class) public int addVisitorApply(VisitorApply visitorApply) { - // TODO: 2022/7/26 数据重复处理 + //无需判重,可预约多个时间段 AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); - // TODO: 2022/7/25 ReceptionistId由前端传,数据源自海康,需考虑海康员工唯一标识与我们唯一标识对应问题 //将时间转换为海康ISO8601格式 DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); - - appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getReceptionistId()); + //海康员工唯一标识receptionistId就是我们录入的到海康的员工号 + appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getStaffCode()); appointmentFreeRegisterRequest.setPersonNum(1); appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); @@ -73,6 +90,7 @@ visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); visitorInfo.setCertificateNo(visitorApply.getIdCard()); visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); @@ -82,26 +100,191 @@ log.error("请求海康,预约免登记失败,海康response:{}", resultStr); return 0; } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); return visitorApplyMapper.insert(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int updateVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + //修改海康访客预约 + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setAppointRecordId(visitorApply1.getAppointRecordId()); + appointmentFreeRegisterRequest.setReceptionistId(visitorApply1.getStaffCode()); + DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(visitorApply.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(visitorApply.getVisitorName()); + visitorInfo.setGender(visitorApply.getVisitorGender()); + visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); + visitorInfo.setCertificateNo(visitorApply.getIdCard()); + visitorInfo.setCertificateType(111); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); + } + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + + String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_UPDATE, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,修改访客预约失败,海康response:{}", resultStr); + return 0; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); + } return visitorApplyMapper.updateById(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + if(StringUtils.isNotEmpty(visitorApply1.getAppointRecordId())){ + List appointRecordIds = new ArrayList<>(); + appointRecordIds.add(visitorApply.getAppointRecordId()); + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("该访客:{},未在海康进行预约成功,无法取消预约", visitorApply.getVisitorName()); + return 0; + } return visitorApplyMapper.deleteById(visitorApply.getId()); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteBatchVisitorApply(List ids) { + List visitorApplies = visitorApplyMapper.selectBatchIds(ids); + List appointRecordIds = visitorApplies.stream().map(VisitorApply::getAppointRecordId).collect(Collectors.toList()); + if(!CollectionUtils.isEmpty(appointRecordIds)){ + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,批量取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("访客列表:{},未在海康进行预约成功,无法取消预约", appointRecordIds); + return 0; + } return deleteBatchVisitorApply(ids); } @Override public List addVisitorApplyBatch(List results) { - return null; + BeanPropertyBindingResult beanPropertyBindingResult = new BeanPropertyBindingResult(CaseInfo.class, "访客申请导入校验"); + List list = new ArrayList<>(); + if (!CollectionUtil.isEmpty(results)) { + final Integer[] index = {0}; + List appointList = new ArrayList<>(); + results.forEach(busConcentrator -> { + validator.validate(busConcentrator, beanPropertyBindingResult); + index[0]++; + if (beanPropertyBindingResult.hasErrors()) { + List errors = beanPropertyBindingResult.getFieldErrors(); + errors.forEach(error -> { + list.add(" 第" + index[0] + "行,".concat(error.getDefaultMessage())); + return; + } + ); + return; + } + if (StrUtil.isNotEmpty(busConcentrator.getInTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getInTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + if (StrUtil.isNotEmpty(busConcentrator.getOutTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getOutTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + DateTime inTimeDate = DateUtil.parse(busConcentrator.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(busConcentrator.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setReceptionistId(busConcentrator.getStaffCode()); + appointmentFreeRegisterRequest.setPersonNum(1); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(busConcentrator.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(busConcentrator.getVisitorName()); + visitorInfo.setGender(busConcentrator.getVisitorGender()); + visitorInfo.setPhoneNo(busConcentrator.getVisitorPhone()); + visitorInfo.setCertificateNo(busConcentrator.getIdCard()); + visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(busConcentrator.getPicUri()); + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + appointList.add(appointmentFreeRegisterRequest); + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + appointList.forEach(app -> { + String body = JSONObject.toJSONString(app); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_FREE_REGISTER, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,预约免登记失败,海康response:{}", resultStr); + list.add("请求海康,预约免登记失败,访客姓名:"+app.getVisitorInfo().getVisitorName()); + return; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + for (VisitorApply result : results) { + //身份证判断同一访客,设置访客信息 + if(result.getIdCard().equals(app.getVisitorInfo().getCertificateNo())){ + result.setAppointRecordId(appointRecordId); + result.setOrderId(orderId); + result.setPicUri(picUri); + } + } + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + this.saveBatch(results); + } + return list; } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java new file mode 100644 index 0000000..511f014 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java @@ -0,0 +1,24 @@ +package com.casic.missiles.modular.util; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 11:09 + */ +@Slf4j +@Component +public class ThreadPoolUtil { + public static ExecutorService executorService; + + @PostConstruct + public void initExecutorService() { + executorService = Executors.newFixedThreadPool(10); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java b/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java index 9b4155c..5c7f422 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java @@ -1,5 +1,6 @@ package com.casic.missiles.modular.util; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.websocket.OnClose; @@ -18,6 +19,7 @@ * @Author: wangpeng * @Date: 2022/7/17 11:48 */ +@Slf4j @Component @ServerEndpoint("/websocket/{userId}") public class WebSocket { @@ -31,27 +33,32 @@ this.session = session; webSockets.add(this); sessionPool.put(userId, session); - System.out.println(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); + log.info(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); +// System.out.println(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); } @OnClose public void onClose() { webSockets.remove(this); - System.out.println("【websocket消息】连接断开,总数为:" + webSockets.size()); + log.info("【websocket消息】连接断开,总数为:" + webSockets.size()); +// System.out.println("【websocket消息】连接断开,总数为:" + webSockets.size()); } @OnMessage public void onMessage(String message) { - System.out.println("【websocket消息】收到客户端消息:" + message); + log.info("【websocket消息】收到客户端消息:" + message); +// System.out.println("【websocket消息】收到客户端消息:" + message); } // 此为广播消息 public void sendAllMessage(String message) { for (WebSocket webSocket : webSockets) { - System.out.println("【websocket消息】广播消息:" + message); + log.info("【websocket消息】广播消息:" + message); +// System.out.println("【websocket消息】广播消息:" + message); try { webSocket.session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】广播消息发送异常"); e.printStackTrace(); } } @@ -59,44 +66,31 @@ // 发送列表消息 public void sendListMessage(List userIds, String message) { - System.out.println("【websocket消息】列表消息:" + message); + log.info("【websocket消息】列表消息:" + message); +// System.out.println("【websocket消息】列表消息:" + message); for (String userId : userIds) { Session session = sessionPool.get(userId); if (session != null) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】列表消息发送异常"); e.printStackTrace(); } } } } - // 发送列表消息 - -// public void sendListMessage(List userIds, Object data){ -// System.out.println("【websocket消息】列表消息:"+data); -// for (String userId : userIds) { -// Session session = sessionPool.get(userId); -// if (session != null) { -// try { -//// session.getAsyncRemote().sendText(message); -// session.getAsyncRemote().sendObject(data); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } -// } -// } - // 此为单点消息 public void sendOneMessage(String userId, String message) { - System.out.println("【websocket消息】单点消息:" + message); + log.info("【websocket消息】单点消息:" + message); +// System.out.println("【websocket消息】单点消息:" + message); Session session = sessionPool.get(userId); if (session != null) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】单点消息发送异常"); e.printStackTrace(); } } diff --git a/casic-web/pom.xml b/casic-web/pom.xml index 53f549f..12786de 100644 --- a/casic-web/pom.xml +++ b/casic-web/pom.xml @@ -56,6 +56,10 @@ org.springframework.boot spring-boot-starter-jdbc + + org.springframework.boot + spring-boot-starter-data-redis + com.casic diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java index 1b8ac75..8f47b37 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.casic.missiles.modular.dto.hik.FacePic; import com.casic.missiles.modular.dto.hik.FaceSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.BlackInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.BlackInfoService; @@ -52,7 +53,7 @@ try { List pageList = blackInfoMapper.getBlackInfoListPage(page, blackInfoRequest); pageList.forEach(blackInfo ->{ - blackInfo.setBlackReasonName(dictService.getDictNameByCode("blackReason", blackInfo.getBlackReason())); + blackInfo.setBlackReasonName(dictService.getDictNameByCode(SecurityEventDict.BLACK_REASON, blackInfo.getBlackReason())); }); return pageList; } catch (DataAccessException ex) { @@ -87,8 +88,8 @@ } JSONObject dataJson = (JSONObject)resultJson.get("data"); //设置海康人脸唯一标识、人脸分组唯一标识 - blackInfo.setIndexCode((String) dataJson.get("indexCode")); - blackInfo.setFaceGroupIndexCode((String) dataJson.get("faceGroupIndexCode")); + blackInfo.setIndexCode(String.valueOf(dataJson.get("indexCode"))); + blackInfo.setFaceGroupIndexCode(String.valueOf(dataJson.get("faceGroupIndexCode"))); //保存图片到本地 String picUrl = fileService.saveFile(blackInfo.getPicture()); blackInfo.setPicture(picUrl); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java index d1057e5..6fa536c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java @@ -7,6 +7,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.CaseInfoMapper; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.CaseInfoService; import lombok.extern.slf4j.Slf4j; @@ -45,10 +46,10 @@ try { List pageList = caseInfoMapper.getCaseInfoListPage(page, caseInfoRequest); pageList.forEach(caseInfo ->{ - caseInfo.setStatusName(dictService.getDictNameByCode("caseStatus", caseInfo.getStatus())); - caseInfo.setPositionName(dictService.getDictNameByCode("devicePosition", caseInfo.getPosition())); - caseInfo.setAreaName(dictService.getDictNameByCode("deviceArea", caseInfo.getArea())); - caseInfo.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", caseInfo.getIsKeyArea())); + caseInfo.setStatusName(dictService.getDictNameByCode(SecurityEventDict.CASE_STATUS, caseInfo.getStatus())); + caseInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, caseInfo.getPosition())); + caseInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, caseInfo.getArea())); + caseInfo.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, caseInfo.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -108,4 +109,9 @@ } return list; } + + @Override + public boolean insertCaseInfoBatch(List caseInfos) { + return this.saveBatch(caseInfos); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java index 849e4f1..9d9c731 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dao.GateGroupMapper; import com.casic.missiles.modular.dao.GroupDeviceMapper; import com.casic.missiles.modular.dto.*; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.DeviceRepairLog; import com.casic.missiles.modular.model.GateGroup; @@ -68,11 +69,11 @@ try { List pageList = deviceInfoMapper.getDeviceInfoListPage(page, deviceInfoRequest); pageList.forEach(device ->{ - device.setDevType(dictService.getDictNameByCode("deviceType", device.getDevType())); - device.setStatus(dictService.getDictNameByCode("deviceStatus", device.getStatus())); - device.setPositionName(dictService.getDictNameByCode("devicePosition", device.getPosition())); - device.setAreaName(dictService.getDictNameByCode("deviceArea", device.getArea())); - device.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", device.getIsKeyArea())); + device.setDevType(dictService.getDictNameByCode(SecurityEventDict.DEVICE_TYPE, device.getDevType())); + device.setStatus(dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, device.getStatus())); + device.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, device.getPosition())); + device.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, device.getArea())); + device.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, device.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -214,7 +215,7 @@ try { List pageList = gateGroupMapper.getGateGroupListPage(page, gateGroupRequest); pageList.forEach(gateGroup ->{ - gateGroup.setStatusName(dictService.getDictNameByCode("groupDeviceStatus", gateGroup.getStatus())); + gateGroup.setStatusName(dictService.getDictNameByCode(SecurityEventDict.GROUP_DEVICE_STATUS, gateGroup.getStatus())); }); return pageList; } catch (DataAccessException ex) { @@ -300,5 +301,11 @@ return deviceCodes; } + @Override + public List selectIndexCodesByCodes(List deviceCodes) { + List indexCodes = deviceInfoMapper.selectIndexCodesByCodes(deviceCodes); + return indexCodes; + } + } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java index 8a5f370..a95fff2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java @@ -8,6 +8,7 @@ import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.dao.FireEquipInfoMapper; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.FireEquipInfo; import com.casic.missiles.modular.service.FireEquipService; @@ -48,10 +49,10 @@ try { List pageList = fireEquipInfoMapper.getFireEquipInfoListPage(page, fireEquipRequest); pageList.forEach(equipInfo ->{ - equipInfo.setEquipTypeName(dictService.getDictNameByCode("equipType", equipInfo.getEquipType())); - equipInfo.setFireLevelName(dictService.getDictNameByCode("fireLevel", equipInfo.getFireLevel())); - equipInfo.setPositionName(dictService.getDictNameByCode("devicePosition", equipInfo.getPosition())); - equipInfo.setAreaName(dictService.getDictNameByCode("deviceArea", equipInfo.getArea())); + equipInfo.setEquipTypeName(dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, equipInfo.getEquipType())); + equipInfo.setFireLevelName(dictService.getDictNameByCode(SecurityEventDict.FIRE_LEVEL, equipInfo.getFireLevel())); + equipInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, equipInfo.getPosition())); + equipInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, equipInfo.getArea())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java new file mode 100644 index 0000000..b47f78f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java @@ -0,0 +1,284 @@ +package com.casic.missiles.modular.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.*; +import com.casic.missiles.modular.service.HikService; +import com.casic.missiles.modular.system.model.Dict; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +@Slf4j +@Service +public class HikServiceImpl implements HikService { + + @Resource + private AbstractDictService dictService; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Override + public CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public void propertyAttendanceHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 物业人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增物业人员考勤异常"); + return; + } + } + } + + @Override + public void securityPersonnelHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 安保人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增安保人员考勤异常"); + return; + } + } + } + + @Override + public void visitorRegisterHandler(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("startTime")); + String startTime = DateUtil.formatDateTime(parse); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + VisitInfo visitInfo = new VisitInfo(); + visitInfo.setVisitorName(data.getString("personName")); + visitInfo.setVisitorGender(data.getString("sex")); + visitInfo.setVisitorPhone(data.getString("phone")); + visitInfo.setInTime(startTime); //来访时间 +// visitInfo.setOutTime(); + if("111".equals(data.getString("idType"))){ + visitInfo.setInType("身份证"); + visitInfo.setIdCard(data.getString("idNo")); + } + visitInfo.setVisitReason(data.getString("purpose")); + visitInfo.setPicUri(data.getString("captureUrl")); + visitInfo.setServerIndexCode(data.getString("svrIndexCode")); + visitInfo.setVisitPosition(deviceInfo.getPosition()); + + if(visitInfoMapper.insert(visitInfo) <= 0){ + log.error("新增访客记录异常"); + } + } + + @Override + public void visitorCheckOutHandler(JSONObject event) { + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("endTime")); + String endTime = DateUtil.formatDateTime(parse); + VisitInfo visitInfo = visitInfoMapper.selectByOrderId(data.getString("visitorId")); + if(!Objects.isNull(visitInfo)){ + visitInfo.setOutTime(endTime); + } + if(visitInfoMapper.updateById(visitInfo) <= 0){ + log.error("更新访客记录异常"); + } + } + + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java index 207b95c..b416f5c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dto.hik.PersonBatchDeleteRequest; import com.casic.missiles.modular.dto.hik.PersonSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.StaffInfo; import com.casic.missiles.modular.service.StaffInfoService; @@ -61,7 +62,7 @@ try { List pageList = staffInfoMapper.getStaffInfoListPage(page, staffInfoRequest); pageList.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); String base64 = Base64Util.transformPictureToBase64(uploadPath + staffInfo.getPicture()); staffInfo.setPicture(base64); }); @@ -104,6 +105,9 @@ log.error("请求海康,单个添加人员失败,海康response:{}", resultStr); return ResponseData.error("单个添加人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.insert(staffInfo) > 0){ return ResponseData.success(); } @@ -138,6 +142,9 @@ log.error("请求海康,单个修改人员失败,海康response:{}", resultStr); return ResponseData.error("单个修改人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.updateById(staffInfo) > 0){ return ResponseData.success(); } @@ -254,7 +261,7 @@ try { List list = staffInfoMapper.getStaffInfoList(staffInfoRequest); list.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); }); return list; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java new file mode 100644 index 0000000..39618ea --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java @@ -0,0 +1,53 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +@Slf4j +@Service +public class VisitServiceImpl extends ServiceImpl implements VisitService { + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List visitInfoListPage(Page page, VisitorRequest visitorRequest) { + try { + List pageList = visitInfoMapper.getVisitInfoListPage(page, visitorRequest); + pageList.forEach(visitInfo ->{ + visitInfo.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitInfo.getVisitReason())); + visitInfo.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitInfo.getVisitPosition())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("访客: 查询分页出现异常,异常:{}", ex); + } + return null; + } + + @Override + public VisitInfo visitInfoDetail(String id) { + VisitInfo visitInfo = visitInfoMapper.selectById(id); + return visitInfo; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java index d9fa377..1f3f89b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java @@ -1,7 +1,9 @@ package com.casic.missiles.modular.service.impl; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -11,16 +13,27 @@ import com.casic.missiles.modular.dto.hik.AppointmentFreeRegisterRequest; import com.casic.missiles.modular.dto.hik.VisitorInfo; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.VisitorApply; import com.casic.missiles.modular.service.VisitorApplyService; import com.casic.missiles.modular.util.HikUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.validation.BeanPropertyBindingResult; +import org.springframework.validation.FieldError; +import org.springframework.validation.Validator; import javax.annotation.Resource; +import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * @Description: @@ -36,12 +49,16 @@ @Resource private AbstractDictService dictService; + @Resource + private Validator validator; + @Override public List visitorApplyListPage(Page page, VisitorApplyRequest visitorApplyRequest) { try { List pageList = visitorApplyMapper.getVisitorApplyListPage(page, visitorApplyRequest); pageList.forEach(visitorApply ->{ - visitorApply.setVisitReason(dictService.getDictNameByCode("visitReason", visitorApply.getVisitReason())); + visitorApply.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitorApply.getVisitReason())); + visitorApply.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitorApply.getVisitPosition())); }); return pageList; } catch (DataAccessException ex) { @@ -51,17 +68,17 @@ } @Override + @Transactional(rollbackFor = Exception.class) public int addVisitorApply(VisitorApply visitorApply) { - // TODO: 2022/7/26 数据重复处理 + //无需判重,可预约多个时间段 AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); - // TODO: 2022/7/25 ReceptionistId由前端传,数据源自海康,需考虑海康员工唯一标识与我们唯一标识对应问题 //将时间转换为海康ISO8601格式 DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); - - appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getReceptionistId()); + //海康员工唯一标识receptionistId就是我们录入的到海康的员工号 + appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getStaffCode()); appointmentFreeRegisterRequest.setPersonNum(1); appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); @@ -73,6 +90,7 @@ visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); visitorInfo.setCertificateNo(visitorApply.getIdCard()); visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); @@ -82,26 +100,191 @@ log.error("请求海康,预约免登记失败,海康response:{}", resultStr); return 0; } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); return visitorApplyMapper.insert(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int updateVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + //修改海康访客预约 + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setAppointRecordId(visitorApply1.getAppointRecordId()); + appointmentFreeRegisterRequest.setReceptionistId(visitorApply1.getStaffCode()); + DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(visitorApply.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(visitorApply.getVisitorName()); + visitorInfo.setGender(visitorApply.getVisitorGender()); + visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); + visitorInfo.setCertificateNo(visitorApply.getIdCard()); + visitorInfo.setCertificateType(111); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); + } + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + + String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_UPDATE, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,修改访客预约失败,海康response:{}", resultStr); + return 0; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); + } return visitorApplyMapper.updateById(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + if(StringUtils.isNotEmpty(visitorApply1.getAppointRecordId())){ + List appointRecordIds = new ArrayList<>(); + appointRecordIds.add(visitorApply.getAppointRecordId()); + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("该访客:{},未在海康进行预约成功,无法取消预约", visitorApply.getVisitorName()); + return 0; + } return visitorApplyMapper.deleteById(visitorApply.getId()); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteBatchVisitorApply(List ids) { + List visitorApplies = visitorApplyMapper.selectBatchIds(ids); + List appointRecordIds = visitorApplies.stream().map(VisitorApply::getAppointRecordId).collect(Collectors.toList()); + if(!CollectionUtils.isEmpty(appointRecordIds)){ + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,批量取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("访客列表:{},未在海康进行预约成功,无法取消预约", appointRecordIds); + return 0; + } return deleteBatchVisitorApply(ids); } @Override public List addVisitorApplyBatch(List results) { - return null; + BeanPropertyBindingResult beanPropertyBindingResult = new BeanPropertyBindingResult(CaseInfo.class, "访客申请导入校验"); + List list = new ArrayList<>(); + if (!CollectionUtil.isEmpty(results)) { + final Integer[] index = {0}; + List appointList = new ArrayList<>(); + results.forEach(busConcentrator -> { + validator.validate(busConcentrator, beanPropertyBindingResult); + index[0]++; + if (beanPropertyBindingResult.hasErrors()) { + List errors = beanPropertyBindingResult.getFieldErrors(); + errors.forEach(error -> { + list.add(" 第" + index[0] + "行,".concat(error.getDefaultMessage())); + return; + } + ); + return; + } + if (StrUtil.isNotEmpty(busConcentrator.getInTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getInTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + if (StrUtil.isNotEmpty(busConcentrator.getOutTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getOutTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + DateTime inTimeDate = DateUtil.parse(busConcentrator.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(busConcentrator.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setReceptionistId(busConcentrator.getStaffCode()); + appointmentFreeRegisterRequest.setPersonNum(1); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(busConcentrator.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(busConcentrator.getVisitorName()); + visitorInfo.setGender(busConcentrator.getVisitorGender()); + visitorInfo.setPhoneNo(busConcentrator.getVisitorPhone()); + visitorInfo.setCertificateNo(busConcentrator.getIdCard()); + visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(busConcentrator.getPicUri()); + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + appointList.add(appointmentFreeRegisterRequest); + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + appointList.forEach(app -> { + String body = JSONObject.toJSONString(app); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_FREE_REGISTER, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,预约免登记失败,海康response:{}", resultStr); + list.add("请求海康,预约免登记失败,访客姓名:"+app.getVisitorInfo().getVisitorName()); + return; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + for (VisitorApply result : results) { + //身份证判断同一访客,设置访客信息 + if(result.getIdCard().equals(app.getVisitorInfo().getCertificateNo())){ + result.setAppointRecordId(appointRecordId); + result.setOrderId(orderId); + result.setPicUri(picUri); + } + } + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + this.saveBatch(results); + } + return list; } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java new file mode 100644 index 0000000..511f014 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java @@ -0,0 +1,24 @@ +package com.casic.missiles.modular.util; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 11:09 + */ +@Slf4j +@Component +public class ThreadPoolUtil { + public static ExecutorService executorService; + + @PostConstruct + public void initExecutorService() { + executorService = Executors.newFixedThreadPool(10); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java b/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java index 9b4155c..5c7f422 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java @@ -1,5 +1,6 @@ package com.casic.missiles.modular.util; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.websocket.OnClose; @@ -18,6 +19,7 @@ * @Author: wangpeng * @Date: 2022/7/17 11:48 */ +@Slf4j @Component @ServerEndpoint("/websocket/{userId}") public class WebSocket { @@ -31,27 +33,32 @@ this.session = session; webSockets.add(this); sessionPool.put(userId, session); - System.out.println(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); + log.info(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); +// System.out.println(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); } @OnClose public void onClose() { webSockets.remove(this); - System.out.println("【websocket消息】连接断开,总数为:" + webSockets.size()); + log.info("【websocket消息】连接断开,总数为:" + webSockets.size()); +// System.out.println("【websocket消息】连接断开,总数为:" + webSockets.size()); } @OnMessage public void onMessage(String message) { - System.out.println("【websocket消息】收到客户端消息:" + message); + log.info("【websocket消息】收到客户端消息:" + message); +// System.out.println("【websocket消息】收到客户端消息:" + message); } // 此为广播消息 public void sendAllMessage(String message) { for (WebSocket webSocket : webSockets) { - System.out.println("【websocket消息】广播消息:" + message); + log.info("【websocket消息】广播消息:" + message); +// System.out.println("【websocket消息】广播消息:" + message); try { webSocket.session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】广播消息发送异常"); e.printStackTrace(); } } @@ -59,44 +66,31 @@ // 发送列表消息 public void sendListMessage(List userIds, String message) { - System.out.println("【websocket消息】列表消息:" + message); + log.info("【websocket消息】列表消息:" + message); +// System.out.println("【websocket消息】列表消息:" + message); for (String userId : userIds) { Session session = sessionPool.get(userId); if (session != null) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】列表消息发送异常"); e.printStackTrace(); } } } } - // 发送列表消息 - -// public void sendListMessage(List userIds, Object data){ -// System.out.println("【websocket消息】列表消息:"+data); -// for (String userId : userIds) { -// Session session = sessionPool.get(userId); -// if (session != null) { -// try { -//// session.getAsyncRemote().sendText(message); -// session.getAsyncRemote().sendObject(data); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } -// } -// } - // 此为单点消息 public void sendOneMessage(String userId, String message) { - System.out.println("【websocket消息】单点消息:" + message); + log.info("【websocket消息】单点消息:" + message); +// System.out.println("【websocket消息】单点消息:" + message); Session session = sessionPool.get(userId); if (session != null) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】单点消息发送异常"); e.printStackTrace(); } } diff --git a/casic-web/pom.xml b/casic-web/pom.xml index 53f549f..12786de 100644 --- a/casic-web/pom.xml +++ b/casic-web/pom.xml @@ -56,6 +56,10 @@ org.springframework.boot spring-boot-starter-jdbc + + org.springframework.boot + spring-boot-starter-data-redis + com.casic diff --git a/casic-web/src/main/build/bin/start.sh b/casic-web/src/main/build/bin/start.sh index c00b1ef..562149f 100644 --- a/casic-web/src/main/build/bin/start.sh +++ b/casic-web/src/main/build/bin/start.sh @@ -1,2 +1 @@ -java -jar ./lib/${project.build.finalName}.jar - +java -jar ./lib/${project.build.finalName}.jar \ No newline at end of file diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java index 1b8ac75..8f47b37 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.casic.missiles.modular.dto.hik.FacePic; import com.casic.missiles.modular.dto.hik.FaceSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.BlackInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.BlackInfoService; @@ -52,7 +53,7 @@ try { List pageList = blackInfoMapper.getBlackInfoListPage(page, blackInfoRequest); pageList.forEach(blackInfo ->{ - blackInfo.setBlackReasonName(dictService.getDictNameByCode("blackReason", blackInfo.getBlackReason())); + blackInfo.setBlackReasonName(dictService.getDictNameByCode(SecurityEventDict.BLACK_REASON, blackInfo.getBlackReason())); }); return pageList; } catch (DataAccessException ex) { @@ -87,8 +88,8 @@ } JSONObject dataJson = (JSONObject)resultJson.get("data"); //设置海康人脸唯一标识、人脸分组唯一标识 - blackInfo.setIndexCode((String) dataJson.get("indexCode")); - blackInfo.setFaceGroupIndexCode((String) dataJson.get("faceGroupIndexCode")); + blackInfo.setIndexCode(String.valueOf(dataJson.get("indexCode"))); + blackInfo.setFaceGroupIndexCode(String.valueOf(dataJson.get("faceGroupIndexCode"))); //保存图片到本地 String picUrl = fileService.saveFile(blackInfo.getPicture()); blackInfo.setPicture(picUrl); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java index d1057e5..6fa536c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java @@ -7,6 +7,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.CaseInfoMapper; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.CaseInfoService; import lombok.extern.slf4j.Slf4j; @@ -45,10 +46,10 @@ try { List pageList = caseInfoMapper.getCaseInfoListPage(page, caseInfoRequest); pageList.forEach(caseInfo ->{ - caseInfo.setStatusName(dictService.getDictNameByCode("caseStatus", caseInfo.getStatus())); - caseInfo.setPositionName(dictService.getDictNameByCode("devicePosition", caseInfo.getPosition())); - caseInfo.setAreaName(dictService.getDictNameByCode("deviceArea", caseInfo.getArea())); - caseInfo.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", caseInfo.getIsKeyArea())); + caseInfo.setStatusName(dictService.getDictNameByCode(SecurityEventDict.CASE_STATUS, caseInfo.getStatus())); + caseInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, caseInfo.getPosition())); + caseInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, caseInfo.getArea())); + caseInfo.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, caseInfo.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -108,4 +109,9 @@ } return list; } + + @Override + public boolean insertCaseInfoBatch(List caseInfos) { + return this.saveBatch(caseInfos); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java index 849e4f1..9d9c731 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dao.GateGroupMapper; import com.casic.missiles.modular.dao.GroupDeviceMapper; import com.casic.missiles.modular.dto.*; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.DeviceRepairLog; import com.casic.missiles.modular.model.GateGroup; @@ -68,11 +69,11 @@ try { List pageList = deviceInfoMapper.getDeviceInfoListPage(page, deviceInfoRequest); pageList.forEach(device ->{ - device.setDevType(dictService.getDictNameByCode("deviceType", device.getDevType())); - device.setStatus(dictService.getDictNameByCode("deviceStatus", device.getStatus())); - device.setPositionName(dictService.getDictNameByCode("devicePosition", device.getPosition())); - device.setAreaName(dictService.getDictNameByCode("deviceArea", device.getArea())); - device.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", device.getIsKeyArea())); + device.setDevType(dictService.getDictNameByCode(SecurityEventDict.DEVICE_TYPE, device.getDevType())); + device.setStatus(dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, device.getStatus())); + device.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, device.getPosition())); + device.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, device.getArea())); + device.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, device.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -214,7 +215,7 @@ try { List pageList = gateGroupMapper.getGateGroupListPage(page, gateGroupRequest); pageList.forEach(gateGroup ->{ - gateGroup.setStatusName(dictService.getDictNameByCode("groupDeviceStatus", gateGroup.getStatus())); + gateGroup.setStatusName(dictService.getDictNameByCode(SecurityEventDict.GROUP_DEVICE_STATUS, gateGroup.getStatus())); }); return pageList; } catch (DataAccessException ex) { @@ -300,5 +301,11 @@ return deviceCodes; } + @Override + public List selectIndexCodesByCodes(List deviceCodes) { + List indexCodes = deviceInfoMapper.selectIndexCodesByCodes(deviceCodes); + return indexCodes; + } + } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java index 8a5f370..a95fff2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java @@ -8,6 +8,7 @@ import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.dao.FireEquipInfoMapper; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.FireEquipInfo; import com.casic.missiles.modular.service.FireEquipService; @@ -48,10 +49,10 @@ try { List pageList = fireEquipInfoMapper.getFireEquipInfoListPage(page, fireEquipRequest); pageList.forEach(equipInfo ->{ - equipInfo.setEquipTypeName(dictService.getDictNameByCode("equipType", equipInfo.getEquipType())); - equipInfo.setFireLevelName(dictService.getDictNameByCode("fireLevel", equipInfo.getFireLevel())); - equipInfo.setPositionName(dictService.getDictNameByCode("devicePosition", equipInfo.getPosition())); - equipInfo.setAreaName(dictService.getDictNameByCode("deviceArea", equipInfo.getArea())); + equipInfo.setEquipTypeName(dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, equipInfo.getEquipType())); + equipInfo.setFireLevelName(dictService.getDictNameByCode(SecurityEventDict.FIRE_LEVEL, equipInfo.getFireLevel())); + equipInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, equipInfo.getPosition())); + equipInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, equipInfo.getArea())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java new file mode 100644 index 0000000..b47f78f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java @@ -0,0 +1,284 @@ +package com.casic.missiles.modular.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.*; +import com.casic.missiles.modular.service.HikService; +import com.casic.missiles.modular.system.model.Dict; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +@Slf4j +@Service +public class HikServiceImpl implements HikService { + + @Resource + private AbstractDictService dictService; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Override + public CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public void propertyAttendanceHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 物业人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增物业人员考勤异常"); + return; + } + } + } + + @Override + public void securityPersonnelHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 安保人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增安保人员考勤异常"); + return; + } + } + } + + @Override + public void visitorRegisterHandler(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("startTime")); + String startTime = DateUtil.formatDateTime(parse); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + VisitInfo visitInfo = new VisitInfo(); + visitInfo.setVisitorName(data.getString("personName")); + visitInfo.setVisitorGender(data.getString("sex")); + visitInfo.setVisitorPhone(data.getString("phone")); + visitInfo.setInTime(startTime); //来访时间 +// visitInfo.setOutTime(); + if("111".equals(data.getString("idType"))){ + visitInfo.setInType("身份证"); + visitInfo.setIdCard(data.getString("idNo")); + } + visitInfo.setVisitReason(data.getString("purpose")); + visitInfo.setPicUri(data.getString("captureUrl")); + visitInfo.setServerIndexCode(data.getString("svrIndexCode")); + visitInfo.setVisitPosition(deviceInfo.getPosition()); + + if(visitInfoMapper.insert(visitInfo) <= 0){ + log.error("新增访客记录异常"); + } + } + + @Override + public void visitorCheckOutHandler(JSONObject event) { + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("endTime")); + String endTime = DateUtil.formatDateTime(parse); + VisitInfo visitInfo = visitInfoMapper.selectByOrderId(data.getString("visitorId")); + if(!Objects.isNull(visitInfo)){ + visitInfo.setOutTime(endTime); + } + if(visitInfoMapper.updateById(visitInfo) <= 0){ + log.error("更新访客记录异常"); + } + } + + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java index 207b95c..b416f5c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dto.hik.PersonBatchDeleteRequest; import com.casic.missiles.modular.dto.hik.PersonSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.StaffInfo; import com.casic.missiles.modular.service.StaffInfoService; @@ -61,7 +62,7 @@ try { List pageList = staffInfoMapper.getStaffInfoListPage(page, staffInfoRequest); pageList.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); String base64 = Base64Util.transformPictureToBase64(uploadPath + staffInfo.getPicture()); staffInfo.setPicture(base64); }); @@ -104,6 +105,9 @@ log.error("请求海康,单个添加人员失败,海康response:{}", resultStr); return ResponseData.error("单个添加人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.insert(staffInfo) > 0){ return ResponseData.success(); } @@ -138,6 +142,9 @@ log.error("请求海康,单个修改人员失败,海康response:{}", resultStr); return ResponseData.error("单个修改人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.updateById(staffInfo) > 0){ return ResponseData.success(); } @@ -254,7 +261,7 @@ try { List list = staffInfoMapper.getStaffInfoList(staffInfoRequest); list.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); }); return list; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java new file mode 100644 index 0000000..39618ea --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java @@ -0,0 +1,53 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +@Slf4j +@Service +public class VisitServiceImpl extends ServiceImpl implements VisitService { + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List visitInfoListPage(Page page, VisitorRequest visitorRequest) { + try { + List pageList = visitInfoMapper.getVisitInfoListPage(page, visitorRequest); + pageList.forEach(visitInfo ->{ + visitInfo.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitInfo.getVisitReason())); + visitInfo.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitInfo.getVisitPosition())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("访客: 查询分页出现异常,异常:{}", ex); + } + return null; + } + + @Override + public VisitInfo visitInfoDetail(String id) { + VisitInfo visitInfo = visitInfoMapper.selectById(id); + return visitInfo; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java index d9fa377..1f3f89b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java @@ -1,7 +1,9 @@ package com.casic.missiles.modular.service.impl; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -11,16 +13,27 @@ import com.casic.missiles.modular.dto.hik.AppointmentFreeRegisterRequest; import com.casic.missiles.modular.dto.hik.VisitorInfo; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.VisitorApply; import com.casic.missiles.modular.service.VisitorApplyService; import com.casic.missiles.modular.util.HikUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.validation.BeanPropertyBindingResult; +import org.springframework.validation.FieldError; +import org.springframework.validation.Validator; import javax.annotation.Resource; +import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * @Description: @@ -36,12 +49,16 @@ @Resource private AbstractDictService dictService; + @Resource + private Validator validator; + @Override public List visitorApplyListPage(Page page, VisitorApplyRequest visitorApplyRequest) { try { List pageList = visitorApplyMapper.getVisitorApplyListPage(page, visitorApplyRequest); pageList.forEach(visitorApply ->{ - visitorApply.setVisitReason(dictService.getDictNameByCode("visitReason", visitorApply.getVisitReason())); + visitorApply.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitorApply.getVisitReason())); + visitorApply.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitorApply.getVisitPosition())); }); return pageList; } catch (DataAccessException ex) { @@ -51,17 +68,17 @@ } @Override + @Transactional(rollbackFor = Exception.class) public int addVisitorApply(VisitorApply visitorApply) { - // TODO: 2022/7/26 数据重复处理 + //无需判重,可预约多个时间段 AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); - // TODO: 2022/7/25 ReceptionistId由前端传,数据源自海康,需考虑海康员工唯一标识与我们唯一标识对应问题 //将时间转换为海康ISO8601格式 DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); - - appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getReceptionistId()); + //海康员工唯一标识receptionistId就是我们录入的到海康的员工号 + appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getStaffCode()); appointmentFreeRegisterRequest.setPersonNum(1); appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); @@ -73,6 +90,7 @@ visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); visitorInfo.setCertificateNo(visitorApply.getIdCard()); visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); @@ -82,26 +100,191 @@ log.error("请求海康,预约免登记失败,海康response:{}", resultStr); return 0; } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); return visitorApplyMapper.insert(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int updateVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + //修改海康访客预约 + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setAppointRecordId(visitorApply1.getAppointRecordId()); + appointmentFreeRegisterRequest.setReceptionistId(visitorApply1.getStaffCode()); + DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(visitorApply.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(visitorApply.getVisitorName()); + visitorInfo.setGender(visitorApply.getVisitorGender()); + visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); + visitorInfo.setCertificateNo(visitorApply.getIdCard()); + visitorInfo.setCertificateType(111); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); + } + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + + String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_UPDATE, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,修改访客预约失败,海康response:{}", resultStr); + return 0; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); + } return visitorApplyMapper.updateById(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + if(StringUtils.isNotEmpty(visitorApply1.getAppointRecordId())){ + List appointRecordIds = new ArrayList<>(); + appointRecordIds.add(visitorApply.getAppointRecordId()); + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("该访客:{},未在海康进行预约成功,无法取消预约", visitorApply.getVisitorName()); + return 0; + } return visitorApplyMapper.deleteById(visitorApply.getId()); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteBatchVisitorApply(List ids) { + List visitorApplies = visitorApplyMapper.selectBatchIds(ids); + List appointRecordIds = visitorApplies.stream().map(VisitorApply::getAppointRecordId).collect(Collectors.toList()); + if(!CollectionUtils.isEmpty(appointRecordIds)){ + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,批量取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("访客列表:{},未在海康进行预约成功,无法取消预约", appointRecordIds); + return 0; + } return deleteBatchVisitorApply(ids); } @Override public List addVisitorApplyBatch(List results) { - return null; + BeanPropertyBindingResult beanPropertyBindingResult = new BeanPropertyBindingResult(CaseInfo.class, "访客申请导入校验"); + List list = new ArrayList<>(); + if (!CollectionUtil.isEmpty(results)) { + final Integer[] index = {0}; + List appointList = new ArrayList<>(); + results.forEach(busConcentrator -> { + validator.validate(busConcentrator, beanPropertyBindingResult); + index[0]++; + if (beanPropertyBindingResult.hasErrors()) { + List errors = beanPropertyBindingResult.getFieldErrors(); + errors.forEach(error -> { + list.add(" 第" + index[0] + "行,".concat(error.getDefaultMessage())); + return; + } + ); + return; + } + if (StrUtil.isNotEmpty(busConcentrator.getInTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getInTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + if (StrUtil.isNotEmpty(busConcentrator.getOutTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getOutTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + DateTime inTimeDate = DateUtil.parse(busConcentrator.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(busConcentrator.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setReceptionistId(busConcentrator.getStaffCode()); + appointmentFreeRegisterRequest.setPersonNum(1); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(busConcentrator.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(busConcentrator.getVisitorName()); + visitorInfo.setGender(busConcentrator.getVisitorGender()); + visitorInfo.setPhoneNo(busConcentrator.getVisitorPhone()); + visitorInfo.setCertificateNo(busConcentrator.getIdCard()); + visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(busConcentrator.getPicUri()); + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + appointList.add(appointmentFreeRegisterRequest); + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + appointList.forEach(app -> { + String body = JSONObject.toJSONString(app); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_FREE_REGISTER, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,预约免登记失败,海康response:{}", resultStr); + list.add("请求海康,预约免登记失败,访客姓名:"+app.getVisitorInfo().getVisitorName()); + return; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + for (VisitorApply result : results) { + //身份证判断同一访客,设置访客信息 + if(result.getIdCard().equals(app.getVisitorInfo().getCertificateNo())){ + result.setAppointRecordId(appointRecordId); + result.setOrderId(orderId); + result.setPicUri(picUri); + } + } + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + this.saveBatch(results); + } + return list; } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java new file mode 100644 index 0000000..511f014 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java @@ -0,0 +1,24 @@ +package com.casic.missiles.modular.util; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 11:09 + */ +@Slf4j +@Component +public class ThreadPoolUtil { + public static ExecutorService executorService; + + @PostConstruct + public void initExecutorService() { + executorService = Executors.newFixedThreadPool(10); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java b/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java index 9b4155c..5c7f422 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java @@ -1,5 +1,6 @@ package com.casic.missiles.modular.util; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.websocket.OnClose; @@ -18,6 +19,7 @@ * @Author: wangpeng * @Date: 2022/7/17 11:48 */ +@Slf4j @Component @ServerEndpoint("/websocket/{userId}") public class WebSocket { @@ -31,27 +33,32 @@ this.session = session; webSockets.add(this); sessionPool.put(userId, session); - System.out.println(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); + log.info(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); +// System.out.println(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); } @OnClose public void onClose() { webSockets.remove(this); - System.out.println("【websocket消息】连接断开,总数为:" + webSockets.size()); + log.info("【websocket消息】连接断开,总数为:" + webSockets.size()); +// System.out.println("【websocket消息】连接断开,总数为:" + webSockets.size()); } @OnMessage public void onMessage(String message) { - System.out.println("【websocket消息】收到客户端消息:" + message); + log.info("【websocket消息】收到客户端消息:" + message); +// System.out.println("【websocket消息】收到客户端消息:" + message); } // 此为广播消息 public void sendAllMessage(String message) { for (WebSocket webSocket : webSockets) { - System.out.println("【websocket消息】广播消息:" + message); + log.info("【websocket消息】广播消息:" + message); +// System.out.println("【websocket消息】广播消息:" + message); try { webSocket.session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】广播消息发送异常"); e.printStackTrace(); } } @@ -59,44 +66,31 @@ // 发送列表消息 public void sendListMessage(List userIds, String message) { - System.out.println("【websocket消息】列表消息:" + message); + log.info("【websocket消息】列表消息:" + message); +// System.out.println("【websocket消息】列表消息:" + message); for (String userId : userIds) { Session session = sessionPool.get(userId); if (session != null) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】列表消息发送异常"); e.printStackTrace(); } } } } - // 发送列表消息 - -// public void sendListMessage(List userIds, Object data){ -// System.out.println("【websocket消息】列表消息:"+data); -// for (String userId : userIds) { -// Session session = sessionPool.get(userId); -// if (session != null) { -// try { -//// session.getAsyncRemote().sendText(message); -// session.getAsyncRemote().sendObject(data); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } -// } -// } - // 此为单点消息 public void sendOneMessage(String userId, String message) { - System.out.println("【websocket消息】单点消息:" + message); + log.info("【websocket消息】单点消息:" + message); +// System.out.println("【websocket消息】单点消息:" + message); Session session = sessionPool.get(userId); if (session != null) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】单点消息发送异常"); e.printStackTrace(); } } diff --git a/casic-web/pom.xml b/casic-web/pom.xml index 53f549f..12786de 100644 --- a/casic-web/pom.xml +++ b/casic-web/pom.xml @@ -56,6 +56,10 @@ org.springframework.boot spring-boot-starter-jdbc + + org.springframework.boot + spring-boot-starter-data-redis + com.casic diff --git a/casic-web/src/main/build/bin/start.sh b/casic-web/src/main/build/bin/start.sh index c00b1ef..562149f 100644 --- a/casic-web/src/main/build/bin/start.sh +++ b/casic-web/src/main/build/bin/start.sh @@ -1,2 +1 @@ -java -jar ./lib/${project.build.finalName}.jar - +java -jar ./lib/${project.build.finalName}.jar \ No newline at end of file diff --git a/casic-web/src/main/build/bin/teststart.sh b/casic-web/src/main/build/bin/teststart.sh new file mode 100644 index 0000000..d737e70 --- /dev/null +++ b/casic-web/src/main/build/bin/teststart.sh @@ -0,0 +1 @@ +nohup java -jar ./lib/${project.build.finalName}.jar > /dev/null 2>&1 & \ No newline at end of file diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java index 1b8ac75..8f47b37 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.casic.missiles.modular.dto.hik.FacePic; import com.casic.missiles.modular.dto.hik.FaceSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.BlackInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.BlackInfoService; @@ -52,7 +53,7 @@ try { List pageList = blackInfoMapper.getBlackInfoListPage(page, blackInfoRequest); pageList.forEach(blackInfo ->{ - blackInfo.setBlackReasonName(dictService.getDictNameByCode("blackReason", blackInfo.getBlackReason())); + blackInfo.setBlackReasonName(dictService.getDictNameByCode(SecurityEventDict.BLACK_REASON, blackInfo.getBlackReason())); }); return pageList; } catch (DataAccessException ex) { @@ -87,8 +88,8 @@ } JSONObject dataJson = (JSONObject)resultJson.get("data"); //设置海康人脸唯一标识、人脸分组唯一标识 - blackInfo.setIndexCode((String) dataJson.get("indexCode")); - blackInfo.setFaceGroupIndexCode((String) dataJson.get("faceGroupIndexCode")); + blackInfo.setIndexCode(String.valueOf(dataJson.get("indexCode"))); + blackInfo.setFaceGroupIndexCode(String.valueOf(dataJson.get("faceGroupIndexCode"))); //保存图片到本地 String picUrl = fileService.saveFile(blackInfo.getPicture()); blackInfo.setPicture(picUrl); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java index d1057e5..6fa536c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java @@ -7,6 +7,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.CaseInfoMapper; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.CaseInfoService; import lombok.extern.slf4j.Slf4j; @@ -45,10 +46,10 @@ try { List pageList = caseInfoMapper.getCaseInfoListPage(page, caseInfoRequest); pageList.forEach(caseInfo ->{ - caseInfo.setStatusName(dictService.getDictNameByCode("caseStatus", caseInfo.getStatus())); - caseInfo.setPositionName(dictService.getDictNameByCode("devicePosition", caseInfo.getPosition())); - caseInfo.setAreaName(dictService.getDictNameByCode("deviceArea", caseInfo.getArea())); - caseInfo.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", caseInfo.getIsKeyArea())); + caseInfo.setStatusName(dictService.getDictNameByCode(SecurityEventDict.CASE_STATUS, caseInfo.getStatus())); + caseInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, caseInfo.getPosition())); + caseInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, caseInfo.getArea())); + caseInfo.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, caseInfo.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -108,4 +109,9 @@ } return list; } + + @Override + public boolean insertCaseInfoBatch(List caseInfos) { + return this.saveBatch(caseInfos); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java index 849e4f1..9d9c731 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dao.GateGroupMapper; import com.casic.missiles.modular.dao.GroupDeviceMapper; import com.casic.missiles.modular.dto.*; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.DeviceRepairLog; import com.casic.missiles.modular.model.GateGroup; @@ -68,11 +69,11 @@ try { List pageList = deviceInfoMapper.getDeviceInfoListPage(page, deviceInfoRequest); pageList.forEach(device ->{ - device.setDevType(dictService.getDictNameByCode("deviceType", device.getDevType())); - device.setStatus(dictService.getDictNameByCode("deviceStatus", device.getStatus())); - device.setPositionName(dictService.getDictNameByCode("devicePosition", device.getPosition())); - device.setAreaName(dictService.getDictNameByCode("deviceArea", device.getArea())); - device.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", device.getIsKeyArea())); + device.setDevType(dictService.getDictNameByCode(SecurityEventDict.DEVICE_TYPE, device.getDevType())); + device.setStatus(dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, device.getStatus())); + device.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, device.getPosition())); + device.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, device.getArea())); + device.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, device.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -214,7 +215,7 @@ try { List pageList = gateGroupMapper.getGateGroupListPage(page, gateGroupRequest); pageList.forEach(gateGroup ->{ - gateGroup.setStatusName(dictService.getDictNameByCode("groupDeviceStatus", gateGroup.getStatus())); + gateGroup.setStatusName(dictService.getDictNameByCode(SecurityEventDict.GROUP_DEVICE_STATUS, gateGroup.getStatus())); }); return pageList; } catch (DataAccessException ex) { @@ -300,5 +301,11 @@ return deviceCodes; } + @Override + public List selectIndexCodesByCodes(List deviceCodes) { + List indexCodes = deviceInfoMapper.selectIndexCodesByCodes(deviceCodes); + return indexCodes; + } + } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java index 8a5f370..a95fff2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java @@ -8,6 +8,7 @@ import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.dao.FireEquipInfoMapper; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.FireEquipInfo; import com.casic.missiles.modular.service.FireEquipService; @@ -48,10 +49,10 @@ try { List pageList = fireEquipInfoMapper.getFireEquipInfoListPage(page, fireEquipRequest); pageList.forEach(equipInfo ->{ - equipInfo.setEquipTypeName(dictService.getDictNameByCode("equipType", equipInfo.getEquipType())); - equipInfo.setFireLevelName(dictService.getDictNameByCode("fireLevel", equipInfo.getFireLevel())); - equipInfo.setPositionName(dictService.getDictNameByCode("devicePosition", equipInfo.getPosition())); - equipInfo.setAreaName(dictService.getDictNameByCode("deviceArea", equipInfo.getArea())); + equipInfo.setEquipTypeName(dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, equipInfo.getEquipType())); + equipInfo.setFireLevelName(dictService.getDictNameByCode(SecurityEventDict.FIRE_LEVEL, equipInfo.getFireLevel())); + equipInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, equipInfo.getPosition())); + equipInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, equipInfo.getArea())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java new file mode 100644 index 0000000..b47f78f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java @@ -0,0 +1,284 @@ +package com.casic.missiles.modular.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.*; +import com.casic.missiles.modular.service.HikService; +import com.casic.missiles.modular.system.model.Dict; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +@Slf4j +@Service +public class HikServiceImpl implements HikService { + + @Resource + private AbstractDictService dictService; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Override + public CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public void propertyAttendanceHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 物业人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增物业人员考勤异常"); + return; + } + } + } + + @Override + public void securityPersonnelHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 安保人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增安保人员考勤异常"); + return; + } + } + } + + @Override + public void visitorRegisterHandler(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("startTime")); + String startTime = DateUtil.formatDateTime(parse); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + VisitInfo visitInfo = new VisitInfo(); + visitInfo.setVisitorName(data.getString("personName")); + visitInfo.setVisitorGender(data.getString("sex")); + visitInfo.setVisitorPhone(data.getString("phone")); + visitInfo.setInTime(startTime); //来访时间 +// visitInfo.setOutTime(); + if("111".equals(data.getString("idType"))){ + visitInfo.setInType("身份证"); + visitInfo.setIdCard(data.getString("idNo")); + } + visitInfo.setVisitReason(data.getString("purpose")); + visitInfo.setPicUri(data.getString("captureUrl")); + visitInfo.setServerIndexCode(data.getString("svrIndexCode")); + visitInfo.setVisitPosition(deviceInfo.getPosition()); + + if(visitInfoMapper.insert(visitInfo) <= 0){ + log.error("新增访客记录异常"); + } + } + + @Override + public void visitorCheckOutHandler(JSONObject event) { + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("endTime")); + String endTime = DateUtil.formatDateTime(parse); + VisitInfo visitInfo = visitInfoMapper.selectByOrderId(data.getString("visitorId")); + if(!Objects.isNull(visitInfo)){ + visitInfo.setOutTime(endTime); + } + if(visitInfoMapper.updateById(visitInfo) <= 0){ + log.error("更新访客记录异常"); + } + } + + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java index 207b95c..b416f5c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dto.hik.PersonBatchDeleteRequest; import com.casic.missiles.modular.dto.hik.PersonSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.StaffInfo; import com.casic.missiles.modular.service.StaffInfoService; @@ -61,7 +62,7 @@ try { List pageList = staffInfoMapper.getStaffInfoListPage(page, staffInfoRequest); pageList.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); String base64 = Base64Util.transformPictureToBase64(uploadPath + staffInfo.getPicture()); staffInfo.setPicture(base64); }); @@ -104,6 +105,9 @@ log.error("请求海康,单个添加人员失败,海康response:{}", resultStr); return ResponseData.error("单个添加人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.insert(staffInfo) > 0){ return ResponseData.success(); } @@ -138,6 +142,9 @@ log.error("请求海康,单个修改人员失败,海康response:{}", resultStr); return ResponseData.error("单个修改人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.updateById(staffInfo) > 0){ return ResponseData.success(); } @@ -254,7 +261,7 @@ try { List list = staffInfoMapper.getStaffInfoList(staffInfoRequest); list.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); }); return list; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java new file mode 100644 index 0000000..39618ea --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java @@ -0,0 +1,53 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +@Slf4j +@Service +public class VisitServiceImpl extends ServiceImpl implements VisitService { + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List visitInfoListPage(Page page, VisitorRequest visitorRequest) { + try { + List pageList = visitInfoMapper.getVisitInfoListPage(page, visitorRequest); + pageList.forEach(visitInfo ->{ + visitInfo.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitInfo.getVisitReason())); + visitInfo.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitInfo.getVisitPosition())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("访客: 查询分页出现异常,异常:{}", ex); + } + return null; + } + + @Override + public VisitInfo visitInfoDetail(String id) { + VisitInfo visitInfo = visitInfoMapper.selectById(id); + return visitInfo; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java index d9fa377..1f3f89b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java @@ -1,7 +1,9 @@ package com.casic.missiles.modular.service.impl; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -11,16 +13,27 @@ import com.casic.missiles.modular.dto.hik.AppointmentFreeRegisterRequest; import com.casic.missiles.modular.dto.hik.VisitorInfo; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.VisitorApply; import com.casic.missiles.modular.service.VisitorApplyService; import com.casic.missiles.modular.util.HikUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.validation.BeanPropertyBindingResult; +import org.springframework.validation.FieldError; +import org.springframework.validation.Validator; import javax.annotation.Resource; +import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * @Description: @@ -36,12 +49,16 @@ @Resource private AbstractDictService dictService; + @Resource + private Validator validator; + @Override public List visitorApplyListPage(Page page, VisitorApplyRequest visitorApplyRequest) { try { List pageList = visitorApplyMapper.getVisitorApplyListPage(page, visitorApplyRequest); pageList.forEach(visitorApply ->{ - visitorApply.setVisitReason(dictService.getDictNameByCode("visitReason", visitorApply.getVisitReason())); + visitorApply.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitorApply.getVisitReason())); + visitorApply.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitorApply.getVisitPosition())); }); return pageList; } catch (DataAccessException ex) { @@ -51,17 +68,17 @@ } @Override + @Transactional(rollbackFor = Exception.class) public int addVisitorApply(VisitorApply visitorApply) { - // TODO: 2022/7/26 数据重复处理 + //无需判重,可预约多个时间段 AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); - // TODO: 2022/7/25 ReceptionistId由前端传,数据源自海康,需考虑海康员工唯一标识与我们唯一标识对应问题 //将时间转换为海康ISO8601格式 DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); - - appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getReceptionistId()); + //海康员工唯一标识receptionistId就是我们录入的到海康的员工号 + appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getStaffCode()); appointmentFreeRegisterRequest.setPersonNum(1); appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); @@ -73,6 +90,7 @@ visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); visitorInfo.setCertificateNo(visitorApply.getIdCard()); visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); @@ -82,26 +100,191 @@ log.error("请求海康,预约免登记失败,海康response:{}", resultStr); return 0; } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); return visitorApplyMapper.insert(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int updateVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + //修改海康访客预约 + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setAppointRecordId(visitorApply1.getAppointRecordId()); + appointmentFreeRegisterRequest.setReceptionistId(visitorApply1.getStaffCode()); + DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(visitorApply.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(visitorApply.getVisitorName()); + visitorInfo.setGender(visitorApply.getVisitorGender()); + visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); + visitorInfo.setCertificateNo(visitorApply.getIdCard()); + visitorInfo.setCertificateType(111); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); + } + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + + String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_UPDATE, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,修改访客预约失败,海康response:{}", resultStr); + return 0; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); + } return visitorApplyMapper.updateById(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + if(StringUtils.isNotEmpty(visitorApply1.getAppointRecordId())){ + List appointRecordIds = new ArrayList<>(); + appointRecordIds.add(visitorApply.getAppointRecordId()); + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("该访客:{},未在海康进行预约成功,无法取消预约", visitorApply.getVisitorName()); + return 0; + } return visitorApplyMapper.deleteById(visitorApply.getId()); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteBatchVisitorApply(List ids) { + List visitorApplies = visitorApplyMapper.selectBatchIds(ids); + List appointRecordIds = visitorApplies.stream().map(VisitorApply::getAppointRecordId).collect(Collectors.toList()); + if(!CollectionUtils.isEmpty(appointRecordIds)){ + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,批量取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("访客列表:{},未在海康进行预约成功,无法取消预约", appointRecordIds); + return 0; + } return deleteBatchVisitorApply(ids); } @Override public List addVisitorApplyBatch(List results) { - return null; + BeanPropertyBindingResult beanPropertyBindingResult = new BeanPropertyBindingResult(CaseInfo.class, "访客申请导入校验"); + List list = new ArrayList<>(); + if (!CollectionUtil.isEmpty(results)) { + final Integer[] index = {0}; + List appointList = new ArrayList<>(); + results.forEach(busConcentrator -> { + validator.validate(busConcentrator, beanPropertyBindingResult); + index[0]++; + if (beanPropertyBindingResult.hasErrors()) { + List errors = beanPropertyBindingResult.getFieldErrors(); + errors.forEach(error -> { + list.add(" 第" + index[0] + "行,".concat(error.getDefaultMessage())); + return; + } + ); + return; + } + if (StrUtil.isNotEmpty(busConcentrator.getInTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getInTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + if (StrUtil.isNotEmpty(busConcentrator.getOutTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getOutTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + DateTime inTimeDate = DateUtil.parse(busConcentrator.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(busConcentrator.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setReceptionistId(busConcentrator.getStaffCode()); + appointmentFreeRegisterRequest.setPersonNum(1); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(busConcentrator.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(busConcentrator.getVisitorName()); + visitorInfo.setGender(busConcentrator.getVisitorGender()); + visitorInfo.setPhoneNo(busConcentrator.getVisitorPhone()); + visitorInfo.setCertificateNo(busConcentrator.getIdCard()); + visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(busConcentrator.getPicUri()); + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + appointList.add(appointmentFreeRegisterRequest); + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + appointList.forEach(app -> { + String body = JSONObject.toJSONString(app); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_FREE_REGISTER, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,预约免登记失败,海康response:{}", resultStr); + list.add("请求海康,预约免登记失败,访客姓名:"+app.getVisitorInfo().getVisitorName()); + return; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + for (VisitorApply result : results) { + //身份证判断同一访客,设置访客信息 + if(result.getIdCard().equals(app.getVisitorInfo().getCertificateNo())){ + result.setAppointRecordId(appointRecordId); + result.setOrderId(orderId); + result.setPicUri(picUri); + } + } + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + this.saveBatch(results); + } + return list; } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java new file mode 100644 index 0000000..511f014 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java @@ -0,0 +1,24 @@ +package com.casic.missiles.modular.util; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 11:09 + */ +@Slf4j +@Component +public class ThreadPoolUtil { + public static ExecutorService executorService; + + @PostConstruct + public void initExecutorService() { + executorService = Executors.newFixedThreadPool(10); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java b/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java index 9b4155c..5c7f422 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java @@ -1,5 +1,6 @@ package com.casic.missiles.modular.util; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.websocket.OnClose; @@ -18,6 +19,7 @@ * @Author: wangpeng * @Date: 2022/7/17 11:48 */ +@Slf4j @Component @ServerEndpoint("/websocket/{userId}") public class WebSocket { @@ -31,27 +33,32 @@ this.session = session; webSockets.add(this); sessionPool.put(userId, session); - System.out.println(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); + log.info(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); +// System.out.println(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); } @OnClose public void onClose() { webSockets.remove(this); - System.out.println("【websocket消息】连接断开,总数为:" + webSockets.size()); + log.info("【websocket消息】连接断开,总数为:" + webSockets.size()); +// System.out.println("【websocket消息】连接断开,总数为:" + webSockets.size()); } @OnMessage public void onMessage(String message) { - System.out.println("【websocket消息】收到客户端消息:" + message); + log.info("【websocket消息】收到客户端消息:" + message); +// System.out.println("【websocket消息】收到客户端消息:" + message); } // 此为广播消息 public void sendAllMessage(String message) { for (WebSocket webSocket : webSockets) { - System.out.println("【websocket消息】广播消息:" + message); + log.info("【websocket消息】广播消息:" + message); +// System.out.println("【websocket消息】广播消息:" + message); try { webSocket.session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】广播消息发送异常"); e.printStackTrace(); } } @@ -59,44 +66,31 @@ // 发送列表消息 public void sendListMessage(List userIds, String message) { - System.out.println("【websocket消息】列表消息:" + message); + log.info("【websocket消息】列表消息:" + message); +// System.out.println("【websocket消息】列表消息:" + message); for (String userId : userIds) { Session session = sessionPool.get(userId); if (session != null) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】列表消息发送异常"); e.printStackTrace(); } } } } - // 发送列表消息 - -// public void sendListMessage(List userIds, Object data){ -// System.out.println("【websocket消息】列表消息:"+data); -// for (String userId : userIds) { -// Session session = sessionPool.get(userId); -// if (session != null) { -// try { -//// session.getAsyncRemote().sendText(message); -// session.getAsyncRemote().sendObject(data); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } -// } -// } - // 此为单点消息 public void sendOneMessage(String userId, String message) { - System.out.println("【websocket消息】单点消息:" + message); + log.info("【websocket消息】单点消息:" + message); +// System.out.println("【websocket消息】单点消息:" + message); Session session = sessionPool.get(userId); if (session != null) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】单点消息发送异常"); e.printStackTrace(); } } diff --git a/casic-web/pom.xml b/casic-web/pom.xml index 53f549f..12786de 100644 --- a/casic-web/pom.xml +++ b/casic-web/pom.xml @@ -56,6 +56,10 @@ org.springframework.boot spring-boot-starter-jdbc + + org.springframework.boot + spring-boot-starter-data-redis + com.casic diff --git a/casic-web/src/main/build/bin/start.sh b/casic-web/src/main/build/bin/start.sh index c00b1ef..562149f 100644 --- a/casic-web/src/main/build/bin/start.sh +++ b/casic-web/src/main/build/bin/start.sh @@ -1,2 +1 @@ -java -jar ./lib/${project.build.finalName}.jar - +java -jar ./lib/${project.build.finalName}.jar \ No newline at end of file diff --git a/casic-web/src/main/build/bin/teststart.sh b/casic-web/src/main/build/bin/teststart.sh new file mode 100644 index 0000000..d737e70 --- /dev/null +++ b/casic-web/src/main/build/bin/teststart.sh @@ -0,0 +1 @@ +nohup java -jar ./lib/${project.build.finalName}.jar > /dev/null 2>&1 & \ No newline at end of file diff --git a/casic-web/src/main/build/package.xml b/casic-web/src/main/build/package.xml index c9259ad..394dd0f 100644 --- a/casic-web/src/main/build/package.xml +++ b/casic-web/src/main/build/package.xml @@ -8,6 +8,7 @@ true + true true diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java index 1b8ac75..8f47b37 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.casic.missiles.modular.dto.hik.FacePic; import com.casic.missiles.modular.dto.hik.FaceSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.BlackInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.BlackInfoService; @@ -52,7 +53,7 @@ try { List pageList = blackInfoMapper.getBlackInfoListPage(page, blackInfoRequest); pageList.forEach(blackInfo ->{ - blackInfo.setBlackReasonName(dictService.getDictNameByCode("blackReason", blackInfo.getBlackReason())); + blackInfo.setBlackReasonName(dictService.getDictNameByCode(SecurityEventDict.BLACK_REASON, blackInfo.getBlackReason())); }); return pageList; } catch (DataAccessException ex) { @@ -87,8 +88,8 @@ } JSONObject dataJson = (JSONObject)resultJson.get("data"); //设置海康人脸唯一标识、人脸分组唯一标识 - blackInfo.setIndexCode((String) dataJson.get("indexCode")); - blackInfo.setFaceGroupIndexCode((String) dataJson.get("faceGroupIndexCode")); + blackInfo.setIndexCode(String.valueOf(dataJson.get("indexCode"))); + blackInfo.setFaceGroupIndexCode(String.valueOf(dataJson.get("faceGroupIndexCode"))); //保存图片到本地 String picUrl = fileService.saveFile(blackInfo.getPicture()); blackInfo.setPicture(picUrl); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java index d1057e5..6fa536c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java @@ -7,6 +7,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.CaseInfoMapper; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.CaseInfoService; import lombok.extern.slf4j.Slf4j; @@ -45,10 +46,10 @@ try { List pageList = caseInfoMapper.getCaseInfoListPage(page, caseInfoRequest); pageList.forEach(caseInfo ->{ - caseInfo.setStatusName(dictService.getDictNameByCode("caseStatus", caseInfo.getStatus())); - caseInfo.setPositionName(dictService.getDictNameByCode("devicePosition", caseInfo.getPosition())); - caseInfo.setAreaName(dictService.getDictNameByCode("deviceArea", caseInfo.getArea())); - caseInfo.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", caseInfo.getIsKeyArea())); + caseInfo.setStatusName(dictService.getDictNameByCode(SecurityEventDict.CASE_STATUS, caseInfo.getStatus())); + caseInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, caseInfo.getPosition())); + caseInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, caseInfo.getArea())); + caseInfo.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, caseInfo.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -108,4 +109,9 @@ } return list; } + + @Override + public boolean insertCaseInfoBatch(List caseInfos) { + return this.saveBatch(caseInfos); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java index 849e4f1..9d9c731 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dao.GateGroupMapper; import com.casic.missiles.modular.dao.GroupDeviceMapper; import com.casic.missiles.modular.dto.*; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.DeviceRepairLog; import com.casic.missiles.modular.model.GateGroup; @@ -68,11 +69,11 @@ try { List pageList = deviceInfoMapper.getDeviceInfoListPage(page, deviceInfoRequest); pageList.forEach(device ->{ - device.setDevType(dictService.getDictNameByCode("deviceType", device.getDevType())); - device.setStatus(dictService.getDictNameByCode("deviceStatus", device.getStatus())); - device.setPositionName(dictService.getDictNameByCode("devicePosition", device.getPosition())); - device.setAreaName(dictService.getDictNameByCode("deviceArea", device.getArea())); - device.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", device.getIsKeyArea())); + device.setDevType(dictService.getDictNameByCode(SecurityEventDict.DEVICE_TYPE, device.getDevType())); + device.setStatus(dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, device.getStatus())); + device.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, device.getPosition())); + device.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, device.getArea())); + device.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, device.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -214,7 +215,7 @@ try { List pageList = gateGroupMapper.getGateGroupListPage(page, gateGroupRequest); pageList.forEach(gateGroup ->{ - gateGroup.setStatusName(dictService.getDictNameByCode("groupDeviceStatus", gateGroup.getStatus())); + gateGroup.setStatusName(dictService.getDictNameByCode(SecurityEventDict.GROUP_DEVICE_STATUS, gateGroup.getStatus())); }); return pageList; } catch (DataAccessException ex) { @@ -300,5 +301,11 @@ return deviceCodes; } + @Override + public List selectIndexCodesByCodes(List deviceCodes) { + List indexCodes = deviceInfoMapper.selectIndexCodesByCodes(deviceCodes); + return indexCodes; + } + } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java index 8a5f370..a95fff2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java @@ -8,6 +8,7 @@ import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.dao.FireEquipInfoMapper; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.FireEquipInfo; import com.casic.missiles.modular.service.FireEquipService; @@ -48,10 +49,10 @@ try { List pageList = fireEquipInfoMapper.getFireEquipInfoListPage(page, fireEquipRequest); pageList.forEach(equipInfo ->{ - equipInfo.setEquipTypeName(dictService.getDictNameByCode("equipType", equipInfo.getEquipType())); - equipInfo.setFireLevelName(dictService.getDictNameByCode("fireLevel", equipInfo.getFireLevel())); - equipInfo.setPositionName(dictService.getDictNameByCode("devicePosition", equipInfo.getPosition())); - equipInfo.setAreaName(dictService.getDictNameByCode("deviceArea", equipInfo.getArea())); + equipInfo.setEquipTypeName(dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, equipInfo.getEquipType())); + equipInfo.setFireLevelName(dictService.getDictNameByCode(SecurityEventDict.FIRE_LEVEL, equipInfo.getFireLevel())); + equipInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, equipInfo.getPosition())); + equipInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, equipInfo.getArea())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java new file mode 100644 index 0000000..b47f78f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java @@ -0,0 +1,284 @@ +package com.casic.missiles.modular.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.*; +import com.casic.missiles.modular.service.HikService; +import com.casic.missiles.modular.system.model.Dict; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +@Slf4j +@Service +public class HikServiceImpl implements HikService { + + @Resource + private AbstractDictService dictService; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Override + public CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public void propertyAttendanceHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 物业人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增物业人员考勤异常"); + return; + } + } + } + + @Override + public void securityPersonnelHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 安保人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增安保人员考勤异常"); + return; + } + } + } + + @Override + public void visitorRegisterHandler(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("startTime")); + String startTime = DateUtil.formatDateTime(parse); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + VisitInfo visitInfo = new VisitInfo(); + visitInfo.setVisitorName(data.getString("personName")); + visitInfo.setVisitorGender(data.getString("sex")); + visitInfo.setVisitorPhone(data.getString("phone")); + visitInfo.setInTime(startTime); //来访时间 +// visitInfo.setOutTime(); + if("111".equals(data.getString("idType"))){ + visitInfo.setInType("身份证"); + visitInfo.setIdCard(data.getString("idNo")); + } + visitInfo.setVisitReason(data.getString("purpose")); + visitInfo.setPicUri(data.getString("captureUrl")); + visitInfo.setServerIndexCode(data.getString("svrIndexCode")); + visitInfo.setVisitPosition(deviceInfo.getPosition()); + + if(visitInfoMapper.insert(visitInfo) <= 0){ + log.error("新增访客记录异常"); + } + } + + @Override + public void visitorCheckOutHandler(JSONObject event) { + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("endTime")); + String endTime = DateUtil.formatDateTime(parse); + VisitInfo visitInfo = visitInfoMapper.selectByOrderId(data.getString("visitorId")); + if(!Objects.isNull(visitInfo)){ + visitInfo.setOutTime(endTime); + } + if(visitInfoMapper.updateById(visitInfo) <= 0){ + log.error("更新访客记录异常"); + } + } + + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java index 207b95c..b416f5c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dto.hik.PersonBatchDeleteRequest; import com.casic.missiles.modular.dto.hik.PersonSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.StaffInfo; import com.casic.missiles.modular.service.StaffInfoService; @@ -61,7 +62,7 @@ try { List pageList = staffInfoMapper.getStaffInfoListPage(page, staffInfoRequest); pageList.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); String base64 = Base64Util.transformPictureToBase64(uploadPath + staffInfo.getPicture()); staffInfo.setPicture(base64); }); @@ -104,6 +105,9 @@ log.error("请求海康,单个添加人员失败,海康response:{}", resultStr); return ResponseData.error("单个添加人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.insert(staffInfo) > 0){ return ResponseData.success(); } @@ -138,6 +142,9 @@ log.error("请求海康,单个修改人员失败,海康response:{}", resultStr); return ResponseData.error("单个修改人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.updateById(staffInfo) > 0){ return ResponseData.success(); } @@ -254,7 +261,7 @@ try { List list = staffInfoMapper.getStaffInfoList(staffInfoRequest); list.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); }); return list; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java new file mode 100644 index 0000000..39618ea --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java @@ -0,0 +1,53 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +@Slf4j +@Service +public class VisitServiceImpl extends ServiceImpl implements VisitService { + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List visitInfoListPage(Page page, VisitorRequest visitorRequest) { + try { + List pageList = visitInfoMapper.getVisitInfoListPage(page, visitorRequest); + pageList.forEach(visitInfo ->{ + visitInfo.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitInfo.getVisitReason())); + visitInfo.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitInfo.getVisitPosition())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("访客: 查询分页出现异常,异常:{}", ex); + } + return null; + } + + @Override + public VisitInfo visitInfoDetail(String id) { + VisitInfo visitInfo = visitInfoMapper.selectById(id); + return visitInfo; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java index d9fa377..1f3f89b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java @@ -1,7 +1,9 @@ package com.casic.missiles.modular.service.impl; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -11,16 +13,27 @@ import com.casic.missiles.modular.dto.hik.AppointmentFreeRegisterRequest; import com.casic.missiles.modular.dto.hik.VisitorInfo; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.VisitorApply; import com.casic.missiles.modular.service.VisitorApplyService; import com.casic.missiles.modular.util.HikUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.validation.BeanPropertyBindingResult; +import org.springframework.validation.FieldError; +import org.springframework.validation.Validator; import javax.annotation.Resource; +import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * @Description: @@ -36,12 +49,16 @@ @Resource private AbstractDictService dictService; + @Resource + private Validator validator; + @Override public List visitorApplyListPage(Page page, VisitorApplyRequest visitorApplyRequest) { try { List pageList = visitorApplyMapper.getVisitorApplyListPage(page, visitorApplyRequest); pageList.forEach(visitorApply ->{ - visitorApply.setVisitReason(dictService.getDictNameByCode("visitReason", visitorApply.getVisitReason())); + visitorApply.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitorApply.getVisitReason())); + visitorApply.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitorApply.getVisitPosition())); }); return pageList; } catch (DataAccessException ex) { @@ -51,17 +68,17 @@ } @Override + @Transactional(rollbackFor = Exception.class) public int addVisitorApply(VisitorApply visitorApply) { - // TODO: 2022/7/26 数据重复处理 + //无需判重,可预约多个时间段 AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); - // TODO: 2022/7/25 ReceptionistId由前端传,数据源自海康,需考虑海康员工唯一标识与我们唯一标识对应问题 //将时间转换为海康ISO8601格式 DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); - - appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getReceptionistId()); + //海康员工唯一标识receptionistId就是我们录入的到海康的员工号 + appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getStaffCode()); appointmentFreeRegisterRequest.setPersonNum(1); appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); @@ -73,6 +90,7 @@ visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); visitorInfo.setCertificateNo(visitorApply.getIdCard()); visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); @@ -82,26 +100,191 @@ log.error("请求海康,预约免登记失败,海康response:{}", resultStr); return 0; } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); return visitorApplyMapper.insert(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int updateVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + //修改海康访客预约 + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setAppointRecordId(visitorApply1.getAppointRecordId()); + appointmentFreeRegisterRequest.setReceptionistId(visitorApply1.getStaffCode()); + DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(visitorApply.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(visitorApply.getVisitorName()); + visitorInfo.setGender(visitorApply.getVisitorGender()); + visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); + visitorInfo.setCertificateNo(visitorApply.getIdCard()); + visitorInfo.setCertificateType(111); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); + } + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + + String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_UPDATE, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,修改访客预约失败,海康response:{}", resultStr); + return 0; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); + } return visitorApplyMapper.updateById(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + if(StringUtils.isNotEmpty(visitorApply1.getAppointRecordId())){ + List appointRecordIds = new ArrayList<>(); + appointRecordIds.add(visitorApply.getAppointRecordId()); + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("该访客:{},未在海康进行预约成功,无法取消预约", visitorApply.getVisitorName()); + return 0; + } return visitorApplyMapper.deleteById(visitorApply.getId()); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteBatchVisitorApply(List ids) { + List visitorApplies = visitorApplyMapper.selectBatchIds(ids); + List appointRecordIds = visitorApplies.stream().map(VisitorApply::getAppointRecordId).collect(Collectors.toList()); + if(!CollectionUtils.isEmpty(appointRecordIds)){ + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,批量取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("访客列表:{},未在海康进行预约成功,无法取消预约", appointRecordIds); + return 0; + } return deleteBatchVisitorApply(ids); } @Override public List addVisitorApplyBatch(List results) { - return null; + BeanPropertyBindingResult beanPropertyBindingResult = new BeanPropertyBindingResult(CaseInfo.class, "访客申请导入校验"); + List list = new ArrayList<>(); + if (!CollectionUtil.isEmpty(results)) { + final Integer[] index = {0}; + List appointList = new ArrayList<>(); + results.forEach(busConcentrator -> { + validator.validate(busConcentrator, beanPropertyBindingResult); + index[0]++; + if (beanPropertyBindingResult.hasErrors()) { + List errors = beanPropertyBindingResult.getFieldErrors(); + errors.forEach(error -> { + list.add(" 第" + index[0] + "行,".concat(error.getDefaultMessage())); + return; + } + ); + return; + } + if (StrUtil.isNotEmpty(busConcentrator.getInTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getInTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + if (StrUtil.isNotEmpty(busConcentrator.getOutTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getOutTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + DateTime inTimeDate = DateUtil.parse(busConcentrator.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(busConcentrator.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setReceptionistId(busConcentrator.getStaffCode()); + appointmentFreeRegisterRequest.setPersonNum(1); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(busConcentrator.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(busConcentrator.getVisitorName()); + visitorInfo.setGender(busConcentrator.getVisitorGender()); + visitorInfo.setPhoneNo(busConcentrator.getVisitorPhone()); + visitorInfo.setCertificateNo(busConcentrator.getIdCard()); + visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(busConcentrator.getPicUri()); + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + appointList.add(appointmentFreeRegisterRequest); + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + appointList.forEach(app -> { + String body = JSONObject.toJSONString(app); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_FREE_REGISTER, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,预约免登记失败,海康response:{}", resultStr); + list.add("请求海康,预约免登记失败,访客姓名:"+app.getVisitorInfo().getVisitorName()); + return; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + for (VisitorApply result : results) { + //身份证判断同一访客,设置访客信息 + if(result.getIdCard().equals(app.getVisitorInfo().getCertificateNo())){ + result.setAppointRecordId(appointRecordId); + result.setOrderId(orderId); + result.setPicUri(picUri); + } + } + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + this.saveBatch(results); + } + return list; } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java new file mode 100644 index 0000000..511f014 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java @@ -0,0 +1,24 @@ +package com.casic.missiles.modular.util; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 11:09 + */ +@Slf4j +@Component +public class ThreadPoolUtil { + public static ExecutorService executorService; + + @PostConstruct + public void initExecutorService() { + executorService = Executors.newFixedThreadPool(10); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java b/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java index 9b4155c..5c7f422 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java @@ -1,5 +1,6 @@ package com.casic.missiles.modular.util; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.websocket.OnClose; @@ -18,6 +19,7 @@ * @Author: wangpeng * @Date: 2022/7/17 11:48 */ +@Slf4j @Component @ServerEndpoint("/websocket/{userId}") public class WebSocket { @@ -31,27 +33,32 @@ this.session = session; webSockets.add(this); sessionPool.put(userId, session); - System.out.println(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); + log.info(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); +// System.out.println(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); } @OnClose public void onClose() { webSockets.remove(this); - System.out.println("【websocket消息】连接断开,总数为:" + webSockets.size()); + log.info("【websocket消息】连接断开,总数为:" + webSockets.size()); +// System.out.println("【websocket消息】连接断开,总数为:" + webSockets.size()); } @OnMessage public void onMessage(String message) { - System.out.println("【websocket消息】收到客户端消息:" + message); + log.info("【websocket消息】收到客户端消息:" + message); +// System.out.println("【websocket消息】收到客户端消息:" + message); } // 此为广播消息 public void sendAllMessage(String message) { for (WebSocket webSocket : webSockets) { - System.out.println("【websocket消息】广播消息:" + message); + log.info("【websocket消息】广播消息:" + message); +// System.out.println("【websocket消息】广播消息:" + message); try { webSocket.session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】广播消息发送异常"); e.printStackTrace(); } } @@ -59,44 +66,31 @@ // 发送列表消息 public void sendListMessage(List userIds, String message) { - System.out.println("【websocket消息】列表消息:" + message); + log.info("【websocket消息】列表消息:" + message); +// System.out.println("【websocket消息】列表消息:" + message); for (String userId : userIds) { Session session = sessionPool.get(userId); if (session != null) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】列表消息发送异常"); e.printStackTrace(); } } } } - // 发送列表消息 - -// public void sendListMessage(List userIds, Object data){ -// System.out.println("【websocket消息】列表消息:"+data); -// for (String userId : userIds) { -// Session session = sessionPool.get(userId); -// if (session != null) { -// try { -//// session.getAsyncRemote().sendText(message); -// session.getAsyncRemote().sendObject(data); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } -// } -// } - // 此为单点消息 public void sendOneMessage(String userId, String message) { - System.out.println("【websocket消息】单点消息:" + message); + log.info("【websocket消息】单点消息:" + message); +// System.out.println("【websocket消息】单点消息:" + message); Session session = sessionPool.get(userId); if (session != null) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】单点消息发送异常"); e.printStackTrace(); } } diff --git a/casic-web/pom.xml b/casic-web/pom.xml index 53f549f..12786de 100644 --- a/casic-web/pom.xml +++ b/casic-web/pom.xml @@ -56,6 +56,10 @@ org.springframework.boot spring-boot-starter-jdbc + + org.springframework.boot + spring-boot-starter-data-redis + com.casic diff --git a/casic-web/src/main/build/bin/start.sh b/casic-web/src/main/build/bin/start.sh index c00b1ef..562149f 100644 --- a/casic-web/src/main/build/bin/start.sh +++ b/casic-web/src/main/build/bin/start.sh @@ -1,2 +1 @@ -java -jar ./lib/${project.build.finalName}.jar - +java -jar ./lib/${project.build.finalName}.jar \ No newline at end of file diff --git a/casic-web/src/main/build/bin/teststart.sh b/casic-web/src/main/build/bin/teststart.sh new file mode 100644 index 0000000..d737e70 --- /dev/null +++ b/casic-web/src/main/build/bin/teststart.sh @@ -0,0 +1 @@ +nohup java -jar ./lib/${project.build.finalName}.jar > /dev/null 2>&1 & \ No newline at end of file diff --git a/casic-web/src/main/build/package.xml b/casic-web/src/main/build/package.xml index c9259ad..394dd0f 100644 --- a/casic-web/src/main/build/package.xml +++ b/casic-web/src/main/build/package.xml @@ -8,6 +8,7 @@ true + true true diff --git a/casic-web/src/main/resources/config/application-dev.yml b/casic-web/src/main/resources/config/application-dev.yml index 48b510b..4712961 100644 --- a/casic-web/src/main/resources/config/application-dev.yml +++ b/casic-web/src/main/resources/config/application-dev.yml @@ -1,5 +1,5 @@ server: - port: 18083 + port: 5903 ################### spring配置 ################### spring: datasource: @@ -7,6 +7,12 @@ url: jdbc:mysql://111.198.10.15:11336/casic_security_cockpit?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true username: root password: Casic203 + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer jms: pub-sub-domain: true # session: @@ -31,4 +37,13 @@ logging: level.root: info level.com.casic: debug - level.org.springframework.web: info \ No newline at end of file + level.org.springframework.web: info + +#所属楼栋及各楼栋内门禁点列表配置 +#1/2/3/4对应字典中4个楼栋 +accessgroup: + configMap: + 1: [1,2,3] + 2: [2,3,4] + 3: [3,4,5] + 4: [4,5,6] \ No newline at end of file diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java index 1b8ac75..8f47b37 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.casic.missiles.modular.dto.hik.FacePic; import com.casic.missiles.modular.dto.hik.FaceSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.BlackInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.BlackInfoService; @@ -52,7 +53,7 @@ try { List pageList = blackInfoMapper.getBlackInfoListPage(page, blackInfoRequest); pageList.forEach(blackInfo ->{ - blackInfo.setBlackReasonName(dictService.getDictNameByCode("blackReason", blackInfo.getBlackReason())); + blackInfo.setBlackReasonName(dictService.getDictNameByCode(SecurityEventDict.BLACK_REASON, blackInfo.getBlackReason())); }); return pageList; } catch (DataAccessException ex) { @@ -87,8 +88,8 @@ } JSONObject dataJson = (JSONObject)resultJson.get("data"); //设置海康人脸唯一标识、人脸分组唯一标识 - blackInfo.setIndexCode((String) dataJson.get("indexCode")); - blackInfo.setFaceGroupIndexCode((String) dataJson.get("faceGroupIndexCode")); + blackInfo.setIndexCode(String.valueOf(dataJson.get("indexCode"))); + blackInfo.setFaceGroupIndexCode(String.valueOf(dataJson.get("faceGroupIndexCode"))); //保存图片到本地 String picUrl = fileService.saveFile(blackInfo.getPicture()); blackInfo.setPicture(picUrl); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java index d1057e5..6fa536c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java @@ -7,6 +7,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.CaseInfoMapper; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.CaseInfoService; import lombok.extern.slf4j.Slf4j; @@ -45,10 +46,10 @@ try { List pageList = caseInfoMapper.getCaseInfoListPage(page, caseInfoRequest); pageList.forEach(caseInfo ->{ - caseInfo.setStatusName(dictService.getDictNameByCode("caseStatus", caseInfo.getStatus())); - caseInfo.setPositionName(dictService.getDictNameByCode("devicePosition", caseInfo.getPosition())); - caseInfo.setAreaName(dictService.getDictNameByCode("deviceArea", caseInfo.getArea())); - caseInfo.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", caseInfo.getIsKeyArea())); + caseInfo.setStatusName(dictService.getDictNameByCode(SecurityEventDict.CASE_STATUS, caseInfo.getStatus())); + caseInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, caseInfo.getPosition())); + caseInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, caseInfo.getArea())); + caseInfo.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, caseInfo.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -108,4 +109,9 @@ } return list; } + + @Override + public boolean insertCaseInfoBatch(List caseInfos) { + return this.saveBatch(caseInfos); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java index 849e4f1..9d9c731 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dao.GateGroupMapper; import com.casic.missiles.modular.dao.GroupDeviceMapper; import com.casic.missiles.modular.dto.*; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.DeviceRepairLog; import com.casic.missiles.modular.model.GateGroup; @@ -68,11 +69,11 @@ try { List pageList = deviceInfoMapper.getDeviceInfoListPage(page, deviceInfoRequest); pageList.forEach(device ->{ - device.setDevType(dictService.getDictNameByCode("deviceType", device.getDevType())); - device.setStatus(dictService.getDictNameByCode("deviceStatus", device.getStatus())); - device.setPositionName(dictService.getDictNameByCode("devicePosition", device.getPosition())); - device.setAreaName(dictService.getDictNameByCode("deviceArea", device.getArea())); - device.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", device.getIsKeyArea())); + device.setDevType(dictService.getDictNameByCode(SecurityEventDict.DEVICE_TYPE, device.getDevType())); + device.setStatus(dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, device.getStatus())); + device.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, device.getPosition())); + device.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, device.getArea())); + device.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, device.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -214,7 +215,7 @@ try { List pageList = gateGroupMapper.getGateGroupListPage(page, gateGroupRequest); pageList.forEach(gateGroup ->{ - gateGroup.setStatusName(dictService.getDictNameByCode("groupDeviceStatus", gateGroup.getStatus())); + gateGroup.setStatusName(dictService.getDictNameByCode(SecurityEventDict.GROUP_DEVICE_STATUS, gateGroup.getStatus())); }); return pageList; } catch (DataAccessException ex) { @@ -300,5 +301,11 @@ return deviceCodes; } + @Override + public List selectIndexCodesByCodes(List deviceCodes) { + List indexCodes = deviceInfoMapper.selectIndexCodesByCodes(deviceCodes); + return indexCodes; + } + } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java index 8a5f370..a95fff2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java @@ -8,6 +8,7 @@ import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.dao.FireEquipInfoMapper; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.FireEquipInfo; import com.casic.missiles.modular.service.FireEquipService; @@ -48,10 +49,10 @@ try { List pageList = fireEquipInfoMapper.getFireEquipInfoListPage(page, fireEquipRequest); pageList.forEach(equipInfo ->{ - equipInfo.setEquipTypeName(dictService.getDictNameByCode("equipType", equipInfo.getEquipType())); - equipInfo.setFireLevelName(dictService.getDictNameByCode("fireLevel", equipInfo.getFireLevel())); - equipInfo.setPositionName(dictService.getDictNameByCode("devicePosition", equipInfo.getPosition())); - equipInfo.setAreaName(dictService.getDictNameByCode("deviceArea", equipInfo.getArea())); + equipInfo.setEquipTypeName(dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, equipInfo.getEquipType())); + equipInfo.setFireLevelName(dictService.getDictNameByCode(SecurityEventDict.FIRE_LEVEL, equipInfo.getFireLevel())); + equipInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, equipInfo.getPosition())); + equipInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, equipInfo.getArea())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java new file mode 100644 index 0000000..b47f78f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java @@ -0,0 +1,284 @@ +package com.casic.missiles.modular.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.*; +import com.casic.missiles.modular.service.HikService; +import com.casic.missiles.modular.system.model.Dict; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +@Slf4j +@Service +public class HikServiceImpl implements HikService { + + @Resource + private AbstractDictService dictService; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Override + public CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public void propertyAttendanceHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 物业人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增物业人员考勤异常"); + return; + } + } + } + + @Override + public void securityPersonnelHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 安保人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增安保人员考勤异常"); + return; + } + } + } + + @Override + public void visitorRegisterHandler(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("startTime")); + String startTime = DateUtil.formatDateTime(parse); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + VisitInfo visitInfo = new VisitInfo(); + visitInfo.setVisitorName(data.getString("personName")); + visitInfo.setVisitorGender(data.getString("sex")); + visitInfo.setVisitorPhone(data.getString("phone")); + visitInfo.setInTime(startTime); //来访时间 +// visitInfo.setOutTime(); + if("111".equals(data.getString("idType"))){ + visitInfo.setInType("身份证"); + visitInfo.setIdCard(data.getString("idNo")); + } + visitInfo.setVisitReason(data.getString("purpose")); + visitInfo.setPicUri(data.getString("captureUrl")); + visitInfo.setServerIndexCode(data.getString("svrIndexCode")); + visitInfo.setVisitPosition(deviceInfo.getPosition()); + + if(visitInfoMapper.insert(visitInfo) <= 0){ + log.error("新增访客记录异常"); + } + } + + @Override + public void visitorCheckOutHandler(JSONObject event) { + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("endTime")); + String endTime = DateUtil.formatDateTime(parse); + VisitInfo visitInfo = visitInfoMapper.selectByOrderId(data.getString("visitorId")); + if(!Objects.isNull(visitInfo)){ + visitInfo.setOutTime(endTime); + } + if(visitInfoMapper.updateById(visitInfo) <= 0){ + log.error("更新访客记录异常"); + } + } + + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java index 207b95c..b416f5c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dto.hik.PersonBatchDeleteRequest; import com.casic.missiles.modular.dto.hik.PersonSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.StaffInfo; import com.casic.missiles.modular.service.StaffInfoService; @@ -61,7 +62,7 @@ try { List pageList = staffInfoMapper.getStaffInfoListPage(page, staffInfoRequest); pageList.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); String base64 = Base64Util.transformPictureToBase64(uploadPath + staffInfo.getPicture()); staffInfo.setPicture(base64); }); @@ -104,6 +105,9 @@ log.error("请求海康,单个添加人员失败,海康response:{}", resultStr); return ResponseData.error("单个添加人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.insert(staffInfo) > 0){ return ResponseData.success(); } @@ -138,6 +142,9 @@ log.error("请求海康,单个修改人员失败,海康response:{}", resultStr); return ResponseData.error("单个修改人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.updateById(staffInfo) > 0){ return ResponseData.success(); } @@ -254,7 +261,7 @@ try { List list = staffInfoMapper.getStaffInfoList(staffInfoRequest); list.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); }); return list; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java new file mode 100644 index 0000000..39618ea --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java @@ -0,0 +1,53 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +@Slf4j +@Service +public class VisitServiceImpl extends ServiceImpl implements VisitService { + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List visitInfoListPage(Page page, VisitorRequest visitorRequest) { + try { + List pageList = visitInfoMapper.getVisitInfoListPage(page, visitorRequest); + pageList.forEach(visitInfo ->{ + visitInfo.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitInfo.getVisitReason())); + visitInfo.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitInfo.getVisitPosition())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("访客: 查询分页出现异常,异常:{}", ex); + } + return null; + } + + @Override + public VisitInfo visitInfoDetail(String id) { + VisitInfo visitInfo = visitInfoMapper.selectById(id); + return visitInfo; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java index d9fa377..1f3f89b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java @@ -1,7 +1,9 @@ package com.casic.missiles.modular.service.impl; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -11,16 +13,27 @@ import com.casic.missiles.modular.dto.hik.AppointmentFreeRegisterRequest; import com.casic.missiles.modular.dto.hik.VisitorInfo; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.VisitorApply; import com.casic.missiles.modular.service.VisitorApplyService; import com.casic.missiles.modular.util.HikUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.validation.BeanPropertyBindingResult; +import org.springframework.validation.FieldError; +import org.springframework.validation.Validator; import javax.annotation.Resource; +import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * @Description: @@ -36,12 +49,16 @@ @Resource private AbstractDictService dictService; + @Resource + private Validator validator; + @Override public List visitorApplyListPage(Page page, VisitorApplyRequest visitorApplyRequest) { try { List pageList = visitorApplyMapper.getVisitorApplyListPage(page, visitorApplyRequest); pageList.forEach(visitorApply ->{ - visitorApply.setVisitReason(dictService.getDictNameByCode("visitReason", visitorApply.getVisitReason())); + visitorApply.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitorApply.getVisitReason())); + visitorApply.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitorApply.getVisitPosition())); }); return pageList; } catch (DataAccessException ex) { @@ -51,17 +68,17 @@ } @Override + @Transactional(rollbackFor = Exception.class) public int addVisitorApply(VisitorApply visitorApply) { - // TODO: 2022/7/26 数据重复处理 + //无需判重,可预约多个时间段 AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); - // TODO: 2022/7/25 ReceptionistId由前端传,数据源自海康,需考虑海康员工唯一标识与我们唯一标识对应问题 //将时间转换为海康ISO8601格式 DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); - - appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getReceptionistId()); + //海康员工唯一标识receptionistId就是我们录入的到海康的员工号 + appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getStaffCode()); appointmentFreeRegisterRequest.setPersonNum(1); appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); @@ -73,6 +90,7 @@ visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); visitorInfo.setCertificateNo(visitorApply.getIdCard()); visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); @@ -82,26 +100,191 @@ log.error("请求海康,预约免登记失败,海康response:{}", resultStr); return 0; } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); return visitorApplyMapper.insert(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int updateVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + //修改海康访客预约 + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setAppointRecordId(visitorApply1.getAppointRecordId()); + appointmentFreeRegisterRequest.setReceptionistId(visitorApply1.getStaffCode()); + DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(visitorApply.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(visitorApply.getVisitorName()); + visitorInfo.setGender(visitorApply.getVisitorGender()); + visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); + visitorInfo.setCertificateNo(visitorApply.getIdCard()); + visitorInfo.setCertificateType(111); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); + } + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + + String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_UPDATE, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,修改访客预约失败,海康response:{}", resultStr); + return 0; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); + } return visitorApplyMapper.updateById(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + if(StringUtils.isNotEmpty(visitorApply1.getAppointRecordId())){ + List appointRecordIds = new ArrayList<>(); + appointRecordIds.add(visitorApply.getAppointRecordId()); + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("该访客:{},未在海康进行预约成功,无法取消预约", visitorApply.getVisitorName()); + return 0; + } return visitorApplyMapper.deleteById(visitorApply.getId()); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteBatchVisitorApply(List ids) { + List visitorApplies = visitorApplyMapper.selectBatchIds(ids); + List appointRecordIds = visitorApplies.stream().map(VisitorApply::getAppointRecordId).collect(Collectors.toList()); + if(!CollectionUtils.isEmpty(appointRecordIds)){ + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,批量取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("访客列表:{},未在海康进行预约成功,无法取消预约", appointRecordIds); + return 0; + } return deleteBatchVisitorApply(ids); } @Override public List addVisitorApplyBatch(List results) { - return null; + BeanPropertyBindingResult beanPropertyBindingResult = new BeanPropertyBindingResult(CaseInfo.class, "访客申请导入校验"); + List list = new ArrayList<>(); + if (!CollectionUtil.isEmpty(results)) { + final Integer[] index = {0}; + List appointList = new ArrayList<>(); + results.forEach(busConcentrator -> { + validator.validate(busConcentrator, beanPropertyBindingResult); + index[0]++; + if (beanPropertyBindingResult.hasErrors()) { + List errors = beanPropertyBindingResult.getFieldErrors(); + errors.forEach(error -> { + list.add(" 第" + index[0] + "行,".concat(error.getDefaultMessage())); + return; + } + ); + return; + } + if (StrUtil.isNotEmpty(busConcentrator.getInTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getInTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + if (StrUtil.isNotEmpty(busConcentrator.getOutTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getOutTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + DateTime inTimeDate = DateUtil.parse(busConcentrator.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(busConcentrator.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setReceptionistId(busConcentrator.getStaffCode()); + appointmentFreeRegisterRequest.setPersonNum(1); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(busConcentrator.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(busConcentrator.getVisitorName()); + visitorInfo.setGender(busConcentrator.getVisitorGender()); + visitorInfo.setPhoneNo(busConcentrator.getVisitorPhone()); + visitorInfo.setCertificateNo(busConcentrator.getIdCard()); + visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(busConcentrator.getPicUri()); + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + appointList.add(appointmentFreeRegisterRequest); + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + appointList.forEach(app -> { + String body = JSONObject.toJSONString(app); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_FREE_REGISTER, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,预约免登记失败,海康response:{}", resultStr); + list.add("请求海康,预约免登记失败,访客姓名:"+app.getVisitorInfo().getVisitorName()); + return; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + for (VisitorApply result : results) { + //身份证判断同一访客,设置访客信息 + if(result.getIdCard().equals(app.getVisitorInfo().getCertificateNo())){ + result.setAppointRecordId(appointRecordId); + result.setOrderId(orderId); + result.setPicUri(picUri); + } + } + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + this.saveBatch(results); + } + return list; } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java new file mode 100644 index 0000000..511f014 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java @@ -0,0 +1,24 @@ +package com.casic.missiles.modular.util; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 11:09 + */ +@Slf4j +@Component +public class ThreadPoolUtil { + public static ExecutorService executorService; + + @PostConstruct + public void initExecutorService() { + executorService = Executors.newFixedThreadPool(10); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java b/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java index 9b4155c..5c7f422 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java @@ -1,5 +1,6 @@ package com.casic.missiles.modular.util; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.websocket.OnClose; @@ -18,6 +19,7 @@ * @Author: wangpeng * @Date: 2022/7/17 11:48 */ +@Slf4j @Component @ServerEndpoint("/websocket/{userId}") public class WebSocket { @@ -31,27 +33,32 @@ this.session = session; webSockets.add(this); sessionPool.put(userId, session); - System.out.println(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); + log.info(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); +// System.out.println(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); } @OnClose public void onClose() { webSockets.remove(this); - System.out.println("【websocket消息】连接断开,总数为:" + webSockets.size()); + log.info("【websocket消息】连接断开,总数为:" + webSockets.size()); +// System.out.println("【websocket消息】连接断开,总数为:" + webSockets.size()); } @OnMessage public void onMessage(String message) { - System.out.println("【websocket消息】收到客户端消息:" + message); + log.info("【websocket消息】收到客户端消息:" + message); +// System.out.println("【websocket消息】收到客户端消息:" + message); } // 此为广播消息 public void sendAllMessage(String message) { for (WebSocket webSocket : webSockets) { - System.out.println("【websocket消息】广播消息:" + message); + log.info("【websocket消息】广播消息:" + message); +// System.out.println("【websocket消息】广播消息:" + message); try { webSocket.session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】广播消息发送异常"); e.printStackTrace(); } } @@ -59,44 +66,31 @@ // 发送列表消息 public void sendListMessage(List userIds, String message) { - System.out.println("【websocket消息】列表消息:" + message); + log.info("【websocket消息】列表消息:" + message); +// System.out.println("【websocket消息】列表消息:" + message); for (String userId : userIds) { Session session = sessionPool.get(userId); if (session != null) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】列表消息发送异常"); e.printStackTrace(); } } } } - // 发送列表消息 - -// public void sendListMessage(List userIds, Object data){ -// System.out.println("【websocket消息】列表消息:"+data); -// for (String userId : userIds) { -// Session session = sessionPool.get(userId); -// if (session != null) { -// try { -//// session.getAsyncRemote().sendText(message); -// session.getAsyncRemote().sendObject(data); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } -// } -// } - // 此为单点消息 public void sendOneMessage(String userId, String message) { - System.out.println("【websocket消息】单点消息:" + message); + log.info("【websocket消息】单点消息:" + message); +// System.out.println("【websocket消息】单点消息:" + message); Session session = sessionPool.get(userId); if (session != null) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】单点消息发送异常"); e.printStackTrace(); } } diff --git a/casic-web/pom.xml b/casic-web/pom.xml index 53f549f..12786de 100644 --- a/casic-web/pom.xml +++ b/casic-web/pom.xml @@ -56,6 +56,10 @@ org.springframework.boot spring-boot-starter-jdbc + + org.springframework.boot + spring-boot-starter-data-redis + com.casic diff --git a/casic-web/src/main/build/bin/start.sh b/casic-web/src/main/build/bin/start.sh index c00b1ef..562149f 100644 --- a/casic-web/src/main/build/bin/start.sh +++ b/casic-web/src/main/build/bin/start.sh @@ -1,2 +1 @@ -java -jar ./lib/${project.build.finalName}.jar - +java -jar ./lib/${project.build.finalName}.jar \ No newline at end of file diff --git a/casic-web/src/main/build/bin/teststart.sh b/casic-web/src/main/build/bin/teststart.sh new file mode 100644 index 0000000..d737e70 --- /dev/null +++ b/casic-web/src/main/build/bin/teststart.sh @@ -0,0 +1 @@ +nohup java -jar ./lib/${project.build.finalName}.jar > /dev/null 2>&1 & \ No newline at end of file diff --git a/casic-web/src/main/build/package.xml b/casic-web/src/main/build/package.xml index c9259ad..394dd0f 100644 --- a/casic-web/src/main/build/package.xml +++ b/casic-web/src/main/build/package.xml @@ -8,6 +8,7 @@ true + true true diff --git a/casic-web/src/main/resources/config/application-dev.yml b/casic-web/src/main/resources/config/application-dev.yml index 48b510b..4712961 100644 --- a/casic-web/src/main/resources/config/application-dev.yml +++ b/casic-web/src/main/resources/config/application-dev.yml @@ -1,5 +1,5 @@ server: - port: 18083 + port: 5903 ################### spring配置 ################### spring: datasource: @@ -7,6 +7,12 @@ url: jdbc:mysql://111.198.10.15:11336/casic_security_cockpit?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true username: root password: Casic203 + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer jms: pub-sub-domain: true # session: @@ -31,4 +37,13 @@ logging: level.root: info level.com.casic: debug - level.org.springframework.web: info \ No newline at end of file + level.org.springframework.web: info + +#所属楼栋及各楼栋内门禁点列表配置 +#1/2/3/4对应字典中4个楼栋 +accessgroup: + configMap: + 1: [1,2,3] + 2: [2,3,4] + 3: [3,4,5] + 4: [4,5,6] \ No newline at end of file diff --git a/casic-web/src/main/resources/config/application-prod.yml b/casic-web/src/main/resources/config/application-prod.yml index f646180..0073ca8 100644 --- a/casic-web/src/main/resources/config/application-prod.yml +++ b/casic-web/src/main/resources/config/application-prod.yml @@ -1,5 +1,5 @@ server: - port: 18083 + port: 5903 # context-path: /callcenter/api ################### spring配置 ################### spring: diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 67a92aa..70883f0 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -66,6 +66,10 @@ casic-export-support ${extension.version} + + org.springframework.data + spring-data-redis + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java new file mode 100644 index 0000000..4a73087 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/aspect/FrontLogAspect.java @@ -0,0 +1,78 @@ +package com.casic.missiles.modular.aspect; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.model.response.ResponseData; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; + +/** + * @Description: Controller层统一日志 + * @Author: wangpeng + * @Date: 2022/8/4 9:03 + */ +@Aspect +@Component +@Slf4j +@Order(Integer.MIN_VALUE) +public class FrontLogAspect { + @Pointcut("execution(* com.casic.missiles.modular.controller..*.*(..))") + public void point() { + } + + @Around("point()") + public Object aroundCheck(ProceedingJoinPoint joinPoint) throws Throwable { +// String requestId = UUID.randomUUID().toString().replace("-", ""); +// MDC.put("requestId", requestId); + long start = System.currentTimeMillis(); + Object result; + String methodName = joinPoint.getSignature().getName(); + Class classTarget = joinPoint.getTarget().getClass(); + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + try { + String args; + if ("GET".equals(request.getMethod())) { + args = request.getQueryString(); + } else { + Object[] param = joinPoint.getArgs(); + if (param != null && param.length > 0) { + args = JSON.toJSONString(param[0]); + } else { + args = ""; + } + } + log.info("ThreadID:{},MethodName:{},RequestURI:{},Param:{},url:{}", + Thread.currentThread().getId(), + classTarget.getName() + "." + methodName, request.getRequestURI(), JSONObject.toJSONString(args), request.getRequestURI()); + result = joinPoint.proceed(); + long duration = System.currentTimeMillis() - start; + log.info("ThreadID:{},MethodName:{},Response:{},TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, JSONObject.toJSONString(result), duration + "ms", request.getRequestURI()); + + return result; + } catch (Throwable e) { + //添加异常抛出 主要是用于全局异常捕获处理 + if (e instanceof ConstraintViolationException) { + throw e; + } + long duration = System.currentTimeMillis() - start; + result = ResponseData.error("系统异常"); + log.error("ThreadID:{},MethodName:{},Exception:{},Response:{}, TimeCost:{},url:{}", + Thread.currentThread().getId(), classTarget.getName() + "." + methodName, ExceptionUtils.getStackTrace(e), result, duration + "ms", request.getRequestURI()); + return result; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java new file mode 100644 index 0000000..1958fae --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/async/ScheduleConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.async; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executors; + +/** + * @Description: 各定时任务异步执行 + * @Author: wangpeng + * @Date: 2022/8/5 9:46 + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java new file mode 100644 index 0000000..60f1d6b --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/AccessGroupConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/2 15:52 + */ +@Data +@Component +@ConfigurationProperties("accessgroup") +public class AccessGroupConfig { + private HashMap> configMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java new file mode 100644 index 0000000..f9c7354 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/config/CaseConfig.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +/** + * @Description: 事件与设备关系配置 + * @Author: wangpeng + * @Date: 2022/7/28 11:32 + */ +@Data +@Component +@ConfigurationProperties("case") +public class CaseConfig { + private HashMap> devMap; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java new file mode 100644 index 0000000..bf8c58c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/AttendanceController.java @@ -0,0 +1,39 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 考勤管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 16:26 + */ +@Slf4j +@RestController +@RequestMapping("/attendanceInfo") +public class AttendanceController extends ExportController { + @Autowired + private AttendanceService attendanceService; + + /** + * 考勤列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody StaffInfoRequest staffInfoRequest) { + Page page = PageFactory.defaultPage(); + List attendanceInfos = attendanceService.attendanceInfoListPage(page, staffInfoRequest); + page.setRecords(attendanceInfos); + return ResponseData.success(super.packForBT(page)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java index bd2b575..0e4fbfc 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/DeviceController.java @@ -206,7 +206,6 @@ @PostMapping("/gateGroup/statusControl") @ResponseBody public Object gateStatusControl(@RequestBody GateGroupDTO gateGroupDTO) { - // TODO: 2022/7/27 海康门禁点反控需要门禁点唯一标识,需到现场导出海康一份再录入咱们平台使用(与设备编号关联上) // TODO: 2022/7/27 门禁状态字典要与海康的状态相同 //0: 常开 //1: 门闭 @@ -219,10 +218,12 @@ log.info("闸机通道状态控制:不存在分组的闸机编号,request:{}", gateGroupDTO); return ResponseData.error("不存在分组下的闸机编号"); } + //根据闸机编号列表获取门禁点唯一标识列表 + List indexCodes = deviceInfoService.selectIndexCodesByCodes(deviceCodes); //海康门禁点反控 DoorControlRequest doorControlRequest = new DoorControlRequest(); //需根据设备编号获取到对应的门禁点唯一标识 -// doorControlRequest.setDoorIndexCodes(); + doorControlRequest.setDoorIndexCodes(indexCodes); doorControlRequest.setControlType(Integer.valueOf(gateGroupDTO.getStatus())); String body = JSONObject.toJSONString(deviceCodes); String resultStr = HikUtil.hikApi(HikUri.DOOR_CONTROL, body); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java index 1a306ef..18ef0f5 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/FireEquipController.java @@ -54,6 +54,7 @@ */ @PostMapping("/{operation}") @ResponseBody +// @BussinessLog("消防器材增删改") public Object operation(@PathVariable(name = "operation") String operateType, @RequestBody FireEquipInfo fireEquipInfo) { if(OperateTypeEnum.ADD.getOperateType().equals(operateType)){ return fireEquipService.addFireEquipInfo(fireEquipInfo); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java index a7cf1f8..d86dc30 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorApplyController.java @@ -30,7 +30,6 @@ @RestController @RequestMapping("/applicationInfo") public class VisitorApplyController extends ExportController { - // TODO: 2022/7/23 访客申请增删改同时要增删改海康的预约,修改访客预约v2接口,取消操作使用取消访客预约 @Autowired private VisitorApplyService visitorApplyService; /** diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java new file mode 100644 index 0000000..14439eb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/VisitorController.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.ExportController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @Description: 访客管理Controller + * @Author: wangpeng + * @Date: 2022/7/28 19:16 + */ +@Slf4j +@RestController +@RequestMapping("/visitInfo") +public class VisitorController extends ExportController { + @Autowired + private VisitService visitService; + + /** + * 访问记录列表(分页) + */ + @PostMapping("/listPage") + @ResponseBody + public Object listPage(@RequestBody VisitorRequest visitorRequest) { + Page page = PageFactory.defaultPage(); + List visitorApplies = visitService.visitInfoListPage(page, visitorRequest); + page.setRecords(visitorApplies); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 访问记录详情 + */ + @PostMapping("/detail") + @ResponseBody + public Object detail(@RequestBody VisitorRequest visitorRequest) { + VisitInfo visitInfo = visitService.visitInfoDetail(visitorRequest.getId()); + return ResponseData.success(visitInfo); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java new file mode 100644 index 0000000..4b92489 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/CockpitController.java @@ -0,0 +1,171 @@ +package com.casic.missiles.modular.controller.cockpit; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.CategoryLevelMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.FireEquipInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseCategoryLevel; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.redis.RedisUtil; +import com.casic.missiles.modular.redis.key.CacheKeys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-前端主动查询相关 + * @Author: wangpeng + * @Date: 2022/7/27 19:46 + */ +@Slf4j +@RestController +@RequestMapping("/cockpit") +public class CockpitController { + @Autowired + private RedisUtil redisUtil; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private CategoryLevelMapper categoryLevelMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private FireEquipInfoMapper fireEquipInfoMapper; + + /** + * 重点区域威胁事件历史统计,计算每个月的各级别事件的数量 + */ + @PostMapping("/case/keyAreaStatistic") + @ResponseBody + public Object keyAreaEventStatistic(@RequestBody MonthAndLevelGroupDTO monthAndLevelGroupDTO) { + Object o = redisUtil.get(CacheKeys.MONTH_STATISTIC_KEY); + List list = JSONArray.parseArray(String.valueOf(o), MonthAndLevelGroupDTO.class); + if(!CollectionUtils.isEmpty(list)){ + Map> resultMap = list.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + return ResponseData.success(resultMap); + } + //查询数据,放入redis + List monthAndLevelGroup = caseInfoMapper.selectByLevelAndMonth(monthAndLevelGroupDTO.getYear()); + Map> resultMap = monthAndLevelGroup.stream().collect(Collectors.groupingBy(MonthAndLevelGroupDTO::getMonth)); + //设置过期时间为每月1号0点 + LocalDateTime midnight = LocalDateTime.now().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0).withSecond(0).withNano(0); + long between = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight); + redisUtil.set(CacheKeys.MONTH_STATISTIC_KEY, JSONObject.toJSONString(monthAndLevelGroup), between); + return ResponseData.success(resultMap); + } + + /** + * 安防事件类别统计 + */ + @GetMapping("/case/categoryStatistics") + @ResponseBody + public Object eventCategoryStatistics() { + List categoryLevelGroup = caseInfoMapper.selectByCategoryLevel(); + categoryLevelGroup.forEach(group -> { + CaseCategoryLevel caseCategoryLevel = categoryLevelMapper.getCaseCategoryLevel(group.getCategoryLevelCode()); + group.setCategoryLevelName(caseCategoryLevel.getName()); + }); + return ResponseData.success(categoryLevelGroup); + } + + /** + * 消防器材类别统计 + */ + @GetMapping("/device/fireEquipStatistics") + @ResponseBody + public Object fireEquipStatistics() { + List equipTypeGroup = fireEquipInfoMapper.selectByEquipType(); + equipTypeGroup.forEach(group -> { + String equipTypeName = dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, group.getEquipTypeCode()); + group.setEquipTypeName(equipTypeName); + }); + return ResponseData.success(equipTypeGroup); + } + + /** + * 闸机速通门统计-设备状态分组计算数量,devType传闸机字典key + * 视频频监控摄像机统计-设备状态分组计算数量,devType传摄像头字典key + */ + @PostMapping("/device/statistics") + @ResponseBody + public Object GateStatusStatistics(@RequestBody GateStatusGroupDTO gateStatusGroupDTO) { + List gateStatusGroup = deviceInfoMapper.selectByType(gateStatusGroupDTO.getDevType()); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = gateStatusGroup.stream().collect(Collectors.summarizingInt(GateStatusGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("无该类设备信息"); + } + gateStatusGroup.forEach(group -> { + String devStatus = dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, group.getStatus()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(devStatus, result+"%"); + }); + resultMap.put("总", sum); + return ResponseData.success(resultMap); + } + + /** + * 安全防护分析,设备加所在楼层评分,计算规则:发生安防事件*类别权重*级别权重算分 + * 优先级3 + */ + @PostMapping("/device/securityScore") + @ResponseBody + public Object SecurityScore(@RequestBody SecurityScoreDTO securityScoreDTO) { + //按发生事件的设备所在的area划分计算评分,当天发生的事件 + String position = securityScoreDTO.getPosition(); + List caseInfos = caseInfoMapper.selectByPosition(position); + //查询各危险级别权重、各类别权重,放入map,避免循环中多次查数据库 + + List securityScoreDTOs = new ArrayList<>(); + caseInfos.forEach(caseInfo -> { + SecurityScoreDTO securityScoreDTO1 = new SecurityScoreDTO(); + securityScoreDTO1.setArea(caseInfo.getArea()); + // TODO: 2022/8/4 楼层评分计算根据产品定义调整 +// caseInfo.get +// securityScoreDTO1.setScore(); + }); + + return null; + } + + /** + * 安防事件时域性频次统计,统计每月安防事件个数 + */ + @PostMapping("/device/securityFrequency") + @ResponseBody + public Object SecurityFrequency(@RequestBody SecurityFrequencyDTO securityFrequencyDTO) { + String year = securityFrequencyDTO.getYear(); + String month = securityFrequencyDTO.getMonth(); + Integer quantity = caseInfoMapper.selectCountByMonth(year, month); + securityFrequencyDTO.setQuantity(quantity); + return ResponseData.success(securityFrequencyDTO); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java new file mode 100644 index 0000000..ba584ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/cockpit/PropertyManageController.java @@ -0,0 +1,204 @@ +package com.casic.missiles.modular.controller.cockpit; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.CaseInfoMapper; +import com.casic.missiles.modular.dao.HazardLevelMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dto.statistics.*; +import com.casic.missiles.modular.model.CaseHazardLevel; +import com.casic.missiles.modular.model.StaffInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱二级页面-物管信息 + * @Author: wangpeng + * @Date: 2022/8/3 15:05 + */ +@Slf4j +@RestController +@RequestMapping("/propertyManage") +public class PropertyManageController { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private HazardLevelMapper hazardLevelMapper; + + /** + * 安防事件时域频次统计,每月的每天安防事件个数 + * 月维度:展示每个月的每天的数据 + */ + @PostMapping("/case/time/keyAreaStatistic") + @ResponseBody + public Object keyAreaTimeStatistic(@RequestBody MonthAndDayGroupDTO monthAndDayGroupDTO) { + String year = monthAndDayGroupDTO.getYear(); + String month = monthAndDayGroupDTO.getMonth(); + List resultList = caseInfoMapper.selectCountByMonthAndDay(year, month); + resultList.forEach(result -> { + result.setYear(year); + result.setMonth(month); + }); + return ResponseData.success(resultList); + } + + /** + * 安防事件频域频次统计,每年的每月/每周各级别安防事件个数 + * 年维度:展示平均每个月和每周的数据 + */ + @PostMapping("/case/frequency/keyAreaStatistic") + @ResponseBody + public Object keyAreaFrequencyStatistic(@RequestBody AvgMonthAndWeekGroupDTO avgMonthAndWeekGroupDTO) { + String year = avgMonthAndWeekGroupDTO.getYear(); + List monthList = caseInfoMapper.selectPreMonthCountByYear(year); + Map> collect = monthList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + HashMap strAvgMap = new HashMap<>(); + for (String key : collect.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + //若年份是本年,则使用个安防级别数量/当前月份数 + //若不是本年,除数为12 + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + monthAndWeekDTO.setMonthQuantity(sum / DateUtil.thisMonth()); +// monthAndWeekDTO.setLevelName(); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + monthAndWeekDTO.setMonthQuantity(sum / 12); + strAvgMap.put(key, monthAndWeekDTO); + } + } + + List weekList = caseInfoMapper.selectPreWeekCountByYear(year); + Map> collect1 = weekList.stream().collect(Collectors.groupingBy(PreMonthOrWeekCaseDTO::getHazardLevelCode)); + for (String key : collect1.keySet()) { + List preMonthOrWeekCaseDTOS = collect.get(key); + int sum = preMonthOrWeekCaseDTOS.stream().mapToInt(PreMonthOrWeekCaseDTO::getQuantity).sum(); + if(year.equals(String.valueOf(DateUtil.thisYear()))){ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / DateUtil.thisWeekOfYear()); + strAvgMap.put(key, monthAndWeekDTO); + } + }else{ + if(!Objects.isNull(strAvgMap.get(key))){ + MonthAndWeekDTO monthAndWeekDTO = strAvgMap.get(key); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + }else{ + MonthAndWeekDTO monthAndWeekDTO = new MonthAndWeekDTO(); + monthAndWeekDTO.setWeekQuantity(sum / 52); + strAvgMap.put(key, monthAndWeekDTO); + } + } + } + avgMonthAndWeekGroupDTO.setMap(strAvgMap); + return ResponseData.success(avgMonthAndWeekGroupDTO); + } + + /** + * 员工出勤率,优先级3 + * 物业/安保人员出勤人数除以物业/安保人员总数,一天有一次记录就算考勤 + */ + @PostMapping("/staff/attendanceRatio") + @ResponseBody + public Object attendanceRatio(@RequestBody AttendanceRatioDTO attendanceRatioDTO) { + //员工类型字典key + String staffType = attendanceRatioDTO.getStaffType(); + String dateDimension = attendanceRatioDTO.getDateDimension(); + List attendanceRatioDTOS = new ArrayList<>(); + //考勤的人数,按员工类型和单次考勤过滤 + if("week".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForWeek(staffType); + }else if("month".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForMonth(staffType); + }else if("year".equals(dateDimension)){ + attendanceRatioDTOS = attendanceInfoMapper.getCountByTypeAndDateForYear(staffType); + } + if(CollectionUtils.isEmpty(attendanceRatioDTOS)){ + return ResponseData.error("该查询条件下,无员工出勤数据!"); + } + + //该类型员工总数 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", staffType); + Integer sum = staffInfoMapper.selectCount(wrapper); + if(sum <= 0){ + return ResponseData.error("该查询条件下,员工管理中无该类型员工数据!"); + } + + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + //计算出勤率 + attendanceRatioDTOS.forEach(attendanceRatio -> { + attendanceRatio.setDateDimension(dateDimension); + attendanceRatio.setStaffType(staffType); + String ratio = numberFormat.format((float) attendanceRatio.getQuantity() / (float) sum * 100); + attendanceRatio.setAttendanceRatio(ratio+"%"); + }); + return ResponseData.success(attendanceRatioDTOS); + } + + /** + * 员工考勤人数变化,功能待定 + */ + + /** + * 重点区域安防事态评估,功能待定 + */ + + /** + * 重点区域威胁事件类型统计,优先级2 + */ + @GetMapping("/case/hazardLevelStatistics") + @ResponseBody + public Object HazardLevelStatistics() { + List hazardLevelGroup = caseInfoMapper.selectByHazardLevel(); + if(CollectionUtils.isEmpty(hazardLevelGroup)){ + log.info("重点区域威胁事件类型统计,无安防事件"); + return ResponseData.error("无安防事件发生!"); + } + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = hazardLevelGroup.stream().collect(Collectors.summarizingInt(HazardLevelGroupDTO::getQuantity)).getSum(); + if(sum <= 0){ + return ResponseData.error("安防事件总数为0"); + } + hazardLevelGroup.forEach(group -> { + CaseHazardLevel caseHazardLevel = hazardLevelMapper.getCaseHazardLevel(group.getLevelCode()); + group.setLevelName(caseHazardLevel.getName()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + group.setLevelRatio(result+"%"); + }); + HazardLevelGroupResponse hazardLevelGroupResponse = new HazardLevelGroupResponse(); + hazardLevelGroupResponse.setHazardLevelGroup(hazardLevelGroup); + hazardLevelGroupResponse.setQuantity(sum); + return ResponseData.success(hazardLevelGroupResponse); + } + + /** + * 设备状态计算系数和评判,优先级3,需确认设备恢复时间是否可以获取 + */ + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java index 15d0e30..4cad1dd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/controller/hik/HikController.java @@ -1,20 +1,26 @@ package com.casic.missiles.modular.controller.hik; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.model.response.ResponseData; -import com.casic.missiles.modular.dto.hik.*; +import com.casic.missiles.modular.dao.HikFaceGroupInfoMapper; +import com.casic.missiles.modular.dto.hik.EventSubscribeRequest; +import com.casic.missiles.modular.dto.hik.FaceGroupAdditionRequest; +import com.casic.missiles.modular.dto.hik.HikRecvEvent; +import com.casic.missiles.modular.dto.hik.OrgBatchAdd; import com.casic.missiles.modular.enums.HikUri; import com.casic.missiles.modular.enums.SecurityEventType; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.CaseInfoService; import com.casic.missiles.modular.service.HikFaceGroupInfoService; +import com.casic.missiles.modular.service.HikService; import com.casic.missiles.modular.util.CaseInfoFactoryUtil; import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.ThreadPoolUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -23,6 +29,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @Description: 海康事件Controller @@ -43,9 +50,15 @@ @Autowired private HikFaceGroupInfoService hikFaceGroupInfoService; + @Autowired + private HikService hikService; + @Value("${server.port}") private int serverPort; + @Autowired + private HikFaceGroupInfoMapper hikFaceGroupInfoMapper; + /** * 海康事件订阅 */ @@ -86,34 +99,87 @@ public Object eventRcv(@RequestBody HikRecvEvent hikRecvEvent) { //1、接收所需事件类型 Long eventType = hikRecvEvent.getEventType(); + log.info("接收到安防事件类型为:{}", eventType); CaseInfo caseInfo = caseInfoFactoryUtil.getCaseInfo(eventType); + //接收到不关心事件直接返回 + if(Objects.isNull(caseInfo)){ + return ResponseData.success(); + } //2、不同事件不同处理,caseInfoFactoryUtil已设置好事件基础定义信息 - // 再为事件添加状态(未解决)、设备编码、设备名称、位置、区域、时间 - // TODO: 2022/7/21 异步处理事件 - // TODO: 2022/7/21 海康安装设备后,应该有设备和位置的对应关系表,可维护在设备表中,获取位置和区域信息 - // TODO: 2022/7/21 位置和区域的概念 - // TODO: 2022/7/21 kafka + // 再为事件添加状态、设备编码、设备名称、位置、区域、时间 + // 异步处理事件 + ThreadPoolUtil.executorService.execute(new Thread(new Runnable() { + @Override + public void run() { + CaseHandle(hikRecvEvent, eventType, caseInfo); + } + })); + + return null; + } + + private void CaseHandle(HikRecvEvent hikRecvEvent, Long eventType, CaseInfo caseInfo) { JSONArray eventArray = hikRecvEvent.getEventArray(); - ArrayList caseInfos = new ArrayList<>(); + List caseInfos = new ArrayList<>(); while (eventArray.stream().iterator().hasNext()) { - // TODO: 2022/7/23 设备过滤,仅将预设置的设备的事件入库,可建立一个设备与事件的表或放入配置中 + CaseInfo caseInfo1 = new CaseInfo(); + BeanUtils.copyProperties(caseInfo, caseInfo1); JSONObject event = (JSONObject) eventArray.stream().iterator().next(); - //ISO8601标准时间格式 - //示例:2018-08-15T 15:53:47.000+08:00 - String happenTimeISO = (String) event.get("happenTime"); - DateTime parse = DateUtil.parse(happenTimeISO); - String happenTime = DateUtil.formatDateTime(parse); - caseInfo.setHappenTime(happenTime); //发生时间 - // caseInfo.setStatus(); //事件状态 - // caseInfo.setDeviceCode(); //设备code - // caseInfo.setDevName(); //设备名 - // caseInfo.setPosition(); //事件位置 - // caseInfo.setAreaName(); //区域 - caseInfos.add(caseInfo); + //5种事件进行不同处理 + if(SecurityEventType.KEY_PERSONNEL_IDENTIFY_EVENT == eventType){ + //判断所属人脸分组 + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceGroupCode = faceMatch.getString("faceGroupCode"); + if (StringUtils.isEmpty(faceGroupCode)) { + return; + } + HikFaceGroupInfo blackListGroup = hikFaceGroupInfoMapper.selectByName("blackList"); + HikFaceGroupInfo propertyPersonnelGroup = hikFaceGroupInfoMapper.selectByName("propertyPersonnel"); + HikFaceGroupInfo securityPersonnelGroup = hikFaceGroupInfoMapper.selectByName("securityPersonnel"); + if (faceGroupCode.equals(blackListGroup.getFaceGroupCode())) { + //黑名单分组处理 + caseInfo1 = hikService.blackListHandle(event, caseInfo1); + }else if(faceGroupCode.equals(propertyPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-物业人员,添加到考勤表 + hikService.propertyAttendanceHandle(event); + }else if(faceGroupCode.equals(securityPersonnelGroup.getFaceGroupCode())){ + //考勤分组处理-安保人员,添加到考勤表 + hikService.securityPersonnelHandle(event); + }else { + return; + } + + }else if(SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT == eventType){ + //离岗事件处理 + caseInfo1 = hikService.demobilizedHandle(event, caseInfo1); + }else if(SecurityEventType.PERSONNEL_GATHER_EVENT == eventType){ + //人员聚集事件处理 + caseInfo1 = hikService.personGatherHandle(event, caseInfo1); + }else if(SecurityEventType.MONITORING_POINT_OFFLINE == eventType){ + //监控点离线事件处理 + caseInfo1 = hikService.monitorPointOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.DEVICE_OFFLINE == eventType){ + //装置离线事件处理 + caseInfo1 = hikService.deviceOfflineHandle(event, caseInfo1); + }else if(SecurityEventType.VISITOR_REGISTER == eventType){ + //记录访客登记记录,添加到访客记录表 + hikService.visitorRegisterHandler(event); + }else if(SecurityEventType.VISITOR_CHECKOUT == eventType){ + //记录访客签离记录 + hikService.visitorCheckOutHandler(event); + } + if(!Objects.isNull(caseInfo1) && !StringUtils.isEmpty(caseInfo1.getHappenTime())){ + caseInfos.add(caseInfo1); + } } //3、安防事件入库 - caseInfoService.addCaseInfoBatch(caseInfos); - return null; + if(!caseInfoService.insertCaseInfoBatch(caseInfos)){ + log.error("安防事件批量入库异常"); + } + return; } /** @@ -131,9 +197,9 @@ return ResponseData.error("添加人脸分组失败"); } JSONObject dataJson = (JSONObject) resultJson.get("data"); - String code = (String) dataJson.get("indexCode"); - String name = (String) dataJson.get("name"); - String description = (String) dataJson.get("description"); + String code = String.valueOf(dataJson.get("indexCode")); + String name = String.valueOf(dataJson.get("name")); + String description = String.valueOf(dataJson.get("description")); HikFaceGroupInfo hikFaceGroupInfo = new HikFaceGroupInfo(); hikFaceGroupInfo.setFaceGroupCode(code); hikFaceGroupInfo.setFaceGroupName(name); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java new file mode 100644 index 0000000..f9e793e --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/AttendanceInfoMapper.java @@ -0,0 +1,29 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.dto.statistics.AttendanceRatioDTO; +import com.casic.missiles.modular.model.AttendanceInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 16:53 + */ +@Mapper +public interface AttendanceInfoMapper extends BaseMapper { + List getAttendanceInfoListPage(@Param("page") Page page, StaffInfoRequest attendanceInfoRequest); + + AttendanceInfo selectByCodeAndDate(@Param("staffCode") String staffCode); + + List getCountByTypeAndDateForWeek(@Param("staffType")String staffType); + + List getCountByTypeAndDateForMonth(@Param("staffType")String staffType); + + List getCountByTypeAndDateForYear(@Param("staffType")String staffType); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java index aa6795d..8b9e67c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/CaseInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.dto.statistics.*; import com.casic.missiles.modular.model.CaseInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,20 @@ List getCaseInfoListPage(@Param("page") Page page, CaseInfoRequest caseInfoRequest); int updateStatusById(CaseInfoRequest caseInfoRequest); + + List selectByLevelAndMonth(@Param("year") String year); + + List selectByCategoryLevel(); + + List selectByHazardLevel(); + + List selectByPosition(@Param("position") String position); + + Integer selectCountByMonth(@Param("year") String year, @Param("month") String month); + + List selectCountByMonthAndDay(@Param("year") String year, @Param("month") String month); + + List selectPreMonthCountByYear(@Param("year") String year); + + List selectPreWeekCountByYear(@Param("year") String year); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java index 49593e8..d39c852 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/DeviceInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.DeviceInfoRequest; +import com.casic.missiles.modular.dto.statistics.GateStatusGroupDTO; import com.casic.missiles.modular.model.DeviceInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,10 @@ List getDeviceInfoListPage(@Param("page") Page page, DeviceInfoRequest deviceInfoRequest); DeviceInfo getDeviceInfo(@Param("devCode") String devCode); + + DeviceInfo getByIndexCode(@Param("srcIndex") String srcIndex); + + List selectIndexCodesByCodes(@Param("deviceCodes") List deviceCodes); + + List selectByType(@Param("devType") String devType); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java index d381a9f..9035c47 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/FireEquipInfoMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.dto.statistics.EquipTypeGroupDTO; import com.casic.missiles.modular.model.FireEquipInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,4 +21,6 @@ List getFireEquipInfoListPage(@Param("page") Page page, FireEquipRequest fireEquipRequest); FireEquipInfo getFireEquipInfo(@Param("equipCode") String equipCode); + + List selectByEquipType(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java new file mode 100644 index 0000000..b1217c5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitInfoMapper.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:42 + */ +@Mapper +public interface VisitInfoMapper extends BaseMapper { + List getVisitInfoListPage(@Param("page") Page page, VisitorRequest visitorRequest); + + VisitInfo selectByOrderId(@Param("orderId") String orderId); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java index 1466090..c09f3c0 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/VisitorApplyMapper.java @@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; import com.casic.missiles.modular.dto.VisitorApplyRequest; import com.casic.missiles.modular.model.VisitorApply; import org.apache.ibatis.annotations.Mapper; @@ -19,5 +20,5 @@ List getVisitorApplyListPage(@Param("page") Page page, VisitorApplyRequest visitorApplyRequest); - int updateStatusById(VisitorApplyRequest visitorApplyRequest); + List selectByVisitReason(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml new file mode 100644 index 0000000..b2ece71 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/AttendanceInfoMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml index 55def84..dff758a 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/CaseInfoMapper.xml @@ -24,4 +24,62 @@ update bus_case_info set status = #{status} where id = #{id} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml index 57bbc47..9a177c2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/DeviceInfoMapper.xml @@ -35,4 +35,26 @@ and dev_code = #{devCode} + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml index 67cdfd5..4aa130b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/FireEquipInfoMapper.xml @@ -29,4 +29,11 @@ and equip_code = #{equipCode} + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml index 2a749f6..557237e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/StaffInfoMapper.xml @@ -12,6 +12,9 @@ and staff_type = #{staffInfoRequest.staffType} + + and phone = #{staffInfoRequest.phone} + ORDER by create_time DESC diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml new file mode 100644 index 0000000..84aa84f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitInfoMapper.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml index d996517..1ee7486 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/dao/mapping/VisitorApplyMapper.xml @@ -12,8 +12,8 @@ and visit_reason = #{visitorApplyRequest.visitReason} - - and visit_area = #{visitorApplyRequest.area} + + and visit_position = #{visitorApplyRequest.position} and date_format(in_time,'%Y-%m-%d') >= #{visitorApplyRequest.startTime,jdbcType=TIMESTAMP} @@ -21,10 +21,11 @@ and date_format(out_time,'%Y-%m-%d') <= #{visitorApplyRequest.endTime,jdbcType=TIMESTAMP} - ORDER by time DESC - - update bus_case_info set status = #{status} where id = #{id} - + \ No newline at end of file diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java index caa1186..e0bcc03 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/StaffInfoRequest.java @@ -11,4 +11,8 @@ public class StaffInfoRequest { private String keywords; private String staffType; + private String phone; + //起止日期,考勤列表使用 + private String startDate; + private String endDate; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java index 7df0c16..1321ea4 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorApplyRequest.java @@ -11,7 +11,7 @@ public class VisitorApplyRequest { private String keywords; private String visitReason; - private String area; + private String position; private String startTime; private String endTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java new file mode 100644 index 0000000..fb11d74 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/VisitorRequest.java @@ -0,0 +1,19 @@ +package com.casic.missiles.modular.dto; + +import lombok.Data; + +/** + * @Description: 访客列表请求实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:17 + */ +@Data +public class VisitorRequest { + //查询详情使用 + private String id; + private String keywords; + private String visitReason; + private String position; + private String startTime; + private String endTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java index 8468315..aaf34cf 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/AppointmentFreeRegisterRequest.java @@ -25,5 +25,7 @@ private Number personNum; //访客信息 private VisitorInfo visitorInfo; + //预约记录ID,修改预约使用 + private String appointRecordId; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java new file mode 100644 index 0000000..4e6ea6c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/DoorEventsRequest.java @@ -0,0 +1,20 @@ +package com.casic.missiles.modular.dto.hik; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 查询门禁点事件V2请求实体 + * @Author: wangpeng + * @Date: 2022/7/29 17:09 + */ +@Data +public class DoorEventsRequest { + private Integer pageNo; + private Integer pageSize; + private String startTime; + private String endTime; + private List doorIndexCodes; + private List eventTypes; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java index 726f37e..73aa316 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/hik/VisitorInfo.java @@ -18,8 +18,10 @@ //联系电话建议填写手机号码 private String phoneNo; //证件类型 - private Number certificateType = 111; + private Number certificateType; //证件号码 private String certificateNo; + //头像base64编码的字节流,图片最大200K,仅支持jpg格式 + private String visitorPhoto; //其他非必填暂不添加 } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java new file mode 100644 index 0000000..514f382 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/ApplyReasonGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 访客预约详情-按访问目的字典值分组计算各分组人数 + * @Author: wangpeng + * @Date: 2022/8/3 12:10 + */ +@Data +public class ApplyReasonGroupDTO { + //访问目的,对应字典key + private String visitReason; + //访问人数 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java new file mode 100644 index 0000000..83f66d0 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AttendanceRatioDTO.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @Description: 出勤率统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 9:24 + */ +@Data +public class AttendanceRatioDTO { + //物业or安保人员,入参 + @JsonIgnore + private String staffType; + //日期维度,周、月、年,入参 + @JsonIgnore + private String dateDimension; + //出勤数量,计算出勤率使用 + private Integer quantity; + //日期,具体周、月、年,出参 + private String date; + //出勤率,出参 + private String attendanceRatio; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java new file mode 100644 index 0000000..4366916 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/AvgMonthAndWeekGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.Map; + +/** + * @Description: 平均每月和每周的数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 14:10 + */ +@Data +public class AvgMonthAndWeekGroupDTO { + //入参 + private String year; + //出参,key:事件类型,value:周和月数据平均值 + private Map map; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java new file mode 100644 index 0000000..0822047 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/CategoryLevelGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件类别统计-按类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:44 + */ +@Data +public class CategoryLevelGroupDTO { + private String categoryLevelCode; + private String categoryLevelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java new file mode 100644 index 0000000..064b6e8 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/EquipTypeGroupDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 消防器材类别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:45 + */ +@Data +public class EquipTypeGroupDTO { + private String equipTypeCode; + private String equipTypeName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java new file mode 100644 index 0000000..8ad65ee --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/GateStatusGroupDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 闸机/摄像机统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 14:22 + */ +@Data +public class GateStatusGroupDTO { + //设备类型 + private String devType; + //设备状态 + private String status; + //设备数量 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java new file mode 100644 index 0000000..2de962a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 按危险级别统计事件实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:03 + */ +@Data +public class HazardLevelGroupDTO { + private String levelCode; + private String levelName; + private Integer quantity; + private String levelRatio; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java new file mode 100644 index 0000000..706a259 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/HazardLevelGroupResponse.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +import java.util.List; + +/** + * @Description: 按危险级别统计事件响应 + * @Author: wangpeng + * @Date: 2022/8/4 11:20 + */ +@Data +public class HazardLevelGroupResponse { + private List hazardLevelGroup; + private Long quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java new file mode 100644 index 0000000..1b20465 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndDayGroupDTO.java @@ -0,0 +1,21 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 物管信息按月维度获取每天数据实体 + * @Author: wangpeng + * @Date: 2022/8/8 13:46 + */ +@Data +public class MonthAndDayGroupDTO { + //入参 + private String year; + //入参 + private String month; + //出参 + private String day; + //出参 + private Integer quantity; + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java new file mode 100644 index 0000000..e350c5d --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndLevelGroupDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 重点区域威胁事件历史统计-按月份与危险级别统计实体 + * @Author: wangpeng + * @Date: 2022/8/3 13:14 + */ +@Data +public class MonthAndLevelGroupDTO { + private String year; + private String month; + private String levelCode; + private String levelName; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java new file mode 100644 index 0000000..7482b2a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/MonthAndWeekDTO.java @@ -0,0 +1,15 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 计算平均每月和每周数据使用 + * @Author: wangpeng + * @Date: 2022/8/8 14:13 + */ +@Data +public class MonthAndWeekDTO { +// private String levelName; + private Integer monthQuantity; + private Integer weekQuantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java new file mode 100644 index 0000000..5d90f66 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/PreMonthOrWeekCaseDTO.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 14:29 + */ +@Data +public class PreMonthOrWeekCaseDTO { + private String hazardLevelCode; + //维度:月或周 + private String dimension; + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java new file mode 100644 index 0000000..f616b4a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityFrequencyDTO.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安防事件时域性频次统计实体 + * @Author: wangpeng + * @Date: 2022/8/4 13:41 + */ +@Data +public class SecurityFrequencyDTO { + //入参 + private String year; + private String month; + //出参 + private Integer quantity; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java new file mode 100644 index 0000000..304d169 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/dto/statistics/SecurityScoreDTO.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.dto.statistics; + +import lombok.Data; + +/** + * @Description: 安全防护分析计算评分实体 + * @Author: wangpeng + * @Date: 2022/8/4 11:46 + */ +@Data +public class SecurityScoreDTO { + //楼栋,入参 + private String position; + //楼层,出参 + private String area; + //评分,出参 + private String score; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java index 564f8a3..6a30786 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/HikUri.java @@ -10,6 +10,10 @@ String EVENT_SUBSCRIBE = "/api/eventService/v1/eventSubscriptionByEventTypes"; //预约免登记 String APPOINTMENT_FREE_REGISTER = "/api/visitor/v1/appointment/registration"; + //修改访客预约 + String APPOINTMENT_UPDATE = "/api/visitor/v2/appointment/update"; + //取消访客预约 + String APPOINTMENT_CANCEL = "/api/visitor/v1/appointment/cancel"; //单个添加人脸分组 String FACEGROUP_SINGLE_ADDITION = "/api/frs/v1/face/group/single/addition"; //单个添加人脸 @@ -30,4 +34,6 @@ String PERSON_BATCH_DELETE = "/api/resource/v1/person/batch/delete"; //门禁点反控 String DOOR_CONTROL = "/api/acs/v1/door/doControl"; + //查询海康门禁点事件v2 + String DOOR_EVENTS = "/api/acs/v2/door/events"; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java new file mode 100644 index 0000000..84e98a5 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventDict.java @@ -0,0 +1,22 @@ +package com.casic.missiles.modular.enums; + +/** + * @Description: 安防事件状态 + * @Author: wangpeng + * @Date: 2022/8/2 11:28 + */ +public interface SecurityEventDict { + String STAFF_TYPE = "staffType"; + String CASE_STATUS = "caseStatus"; + String ASSET_TYPE = "assetType"; + String DEVICE_TYPE = "deviceType"; + String DEVICE_STATUS = "deviceStatus"; + String DEVICE_POSITION = "devicePosition"; + String VISIT_REASON = "visitReason"; + String BLACK_REASON = "blackReason"; + String DEVICE_AREA = "deviceArea"; + String IS_KEY_AREA = "IsKeyArea"; + String GROUP_DEVICE_STATUS = "groupDeviceStatus"; + String EQUIP_TYPE = "equipType"; + String FIRE_LEVEL = "fireLevel"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java index 228ef68..d51034c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/enums/SecurityEventType.java @@ -1,14 +1,13 @@ package com.casic.missiles.modular.enums; /** - * @Description: 安防事件类型 + * @Description: 安防事件类型,已放入数据表中维护海康事件定义,此枚举仅进行事件编号使用 * @Author: wangpeng * @Date: 2022/7/19 11:04 */ public interface SecurityEventType { - // TODO: 2022/7/23 将该枚举类放入数据表中维护海康事件定义 //重点人员识别事件 - Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; + Number KEY_PERSONNEL_IDENTIFY_EVENT = 1644175361; //离岗事件 Number PERSONNEL_DEMOBILIZED_EVENT = 131603; //人员聚集事件 @@ -17,7 +16,22 @@ Number MONITORING_POINT_OFFLINE = 889196545; //装置离线 Number DEVICE_OFFLINE = 199710; + //访客登记 + Number VISITOR_REGISTER = 1392513025; + //访客签离 + Number VISITOR_CHECKOUT = 1392513026; + //合法卡比对通过 + Number CARD_COMPARE_PASS = 198914; + //人脸认证通过 + Number FACE_COMPARE_PASS = 196893; + +// //正常开门 +// Number NORMAL_OPENING = 198913; +// //按钮开门 +// Number DEVICE_OFFLINE = 198916; +// //远程软件开门 +// Number DEVICE_OFFLINE = 198919; // //人脸抓拍事件 // Number FACE_CAPTURE_EVENT = 131614; // //人脸比对事件 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java index 1b9020e..e80c5a1 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/handler/GlobalExceptionHandler.java @@ -3,6 +3,10 @@ import com.casic.missiles.model.response.ResponseData; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DataAccessException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -21,4 +25,26 @@ log.error("操作数据库失败,exception:{}", exception.getMessage()); return ResponseData.error("数据库异常"); } + + @ResponseBody + @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public Object validationExceptionHandler(Exception exception) { + BindingResult bindResult = null; + if (exception instanceof BindException) { + bindResult = ((BindException) exception).getBindingResult(); + } else if (exception instanceof MethodArgumentNotValidException) { + bindResult = ((MethodArgumentNotValidException) exception).getBindingResult(); + } else if (exception instanceof HttpMessageNotReadableException) { + log.error("HttpMessageNotReadableException:{}", exception.getMessage()); + return ResponseData.error("参数错误"); + } + String msg; + if (bindResult != null && bindResult.hasErrors()) { + msg = bindResult.getAllErrors().get(0).getDefaultMessage(); + return ResponseData.error(msg); + } else { + msg = "系统繁忙,请稍后重试..."; + } + return ResponseData.error(msg); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java new file mode 100644 index 0000000..0cfe24a --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/job/BuildingPeopleNumberJob.java @@ -0,0 +1,259 @@ +package com.casic.missiles.modular.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.config.AccessGroupConfig; +import com.casic.missiles.modular.dao.*; +import com.casic.missiles.modular.dto.hik.DoorEventsRequest; +import com.casic.missiles.modular.dto.statistics.ApplyReasonGroupDTO; +import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.enums.SecurityEventType; +import com.casic.missiles.modular.model.CaseInfo; +import com.casic.missiles.modular.model.DeviceInfo; +import com.casic.missiles.modular.model.StaffInfo; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.util.HikUtil; +import com.casic.missiles.modular.util.WebSocket; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.NumberFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 驾驶舱驻留页面-定时推送任务 + * @Author: wangpeng + * @Date: 2022/8/2 16:11 + */ +@Slf4j +@Component +@EnableScheduling +public class BuildingPeopleNumberJob { + @Autowired + private AccessGroupConfig accessGroupConfig; + + @Autowired + private AbstractDictService dictService; + + @Autowired + private WebSocket webSocket; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private CaseInfoMapper caseInfoMapper; + + @Autowired + private VisitorApplyMapper applyMapper; + + /** + * 各楼栋人数计算定时任务 + */ + @Scheduled(initialDelay = 60000, fixedDelay = 60000) + public void buildingPeopleNumber() { + //统计各楼的,查询当天每小时段内人数 + //查询海康门禁点事件v2,只查询当天的,将返回的list中的所有进出类型进行计算,得到当天的人数 + DoorEventsRequest doorEventsRequest = new DoorEventsRequest(); + List eventTypes = new ArrayList<>(); + eventTypes.add(SecurityEventType.CARD_COMPARE_PASS); + eventTypes.add(SecurityEventType.FACE_COMPARE_PASS); + + // TODO: 2022/7/29 将所属楼栋及楼栋内的门禁点列表放到yml中 + HashMap> configMap = accessGroupConfig.getConfigMap(); + HashMap jsonMap = new HashMap<>(); + HashMap resultMap = new HashMap<>(); + Date date = new Date(); + DateTime startTimeDate = DateUtil.beginOfDay(date); + DateTime endTimeDate = DateUtil.endOfDay(date); + String startTime = DateUtil.format(startTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String endTime = DateUtil.format(endTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + configMap.keySet().stream().forEach(key -> { + List doorIndexCodes = configMap.get(key); + doorEventsRequest.setPageNo(1); + doorEventsRequest.setPageSize(1000); + doorEventsRequest.setDoorIndexCodes(doorIndexCodes); //门禁点列表 + doorEventsRequest.setEventTypes(eventTypes); //事件类型列表 + doorEventsRequest.setStartTime(startTime); //开始时间,当日0点 + doorEventsRequest.setEndTime(endTime); //结束时间,当日23:59 + String body = JSONObject.toJSONString(doorEventsRequest); + String resultStr = HikUtil.hikApi(HikUri.DOOR_EVENTS, body); + JSONObject resultJson = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson.get("code"))) { + log.error("请求海康,查询海康门禁点事件v2失败,海康response:{}", resultStr); + return; + } + JSONObject dataJson = (JSONObject)resultJson.get("data"); + if(Objects.isNull(dataJson)){ + return; + } + JSONArray dataArray = (JSONArray)dataJson.get("list"); + if(Objects.isNull(dataArray)){ + return; + } + + //海康分页限制,需循环请求数据 + if((Integer)dataJson.get("totalPage") > 1){ + for (int i = 2; i <=(Integer)dataJson.get("totalPage"); i++) { + doorEventsRequest.setPageNo(i); + String body1 = JSONObject.toJSONString(doorEventsRequest); + String resultStr1 = HikUtil.hikApi(HikUri.DOOR_EVENTS, body1); + JSONObject resultJson1 = (JSONObject) JSONObject.parse(resultStr); + if (!"0".equals(resultJson1.get("code"))) { + log.error("请求海康,循环查询海康门禁点事件v2失败,海康response:{}", resultStr1); + return; + } + JSONObject dataJson1 = (JSONObject)resultJson1.get("data"); + if(Objects.isNull(dataJson1)){ + return; + } + JSONArray dataArray1 = (JSONArray)dataJson1.get("list"); + if(Objects.isNull(dataArray1)){ + return; + } + dataArray.addAll(dataArray1); + } + } + jsonMap.put(key, dataArray); + }); + if (jsonMap.size() != configMap.size()) { + return; + } + + //构造结构 + jsonMap.keySet().forEach(key -> { + JSONArray list = jsonMap.get(key); + if (Objects.isNull(list)) { + log.error("请求海康,查询海康门禁点事件v2,结果list为null,该楼栋为:{}", key); + return; + } + Integer num = 0; + while (list.stream().iterator().hasNext()) { + JSONObject next = (JSONObject) list.stream().iterator().next(); + Integer inAndOutType = next.getInteger("inAndOutType"); + //进门 + if (1 == inAndOutType) { + ++num; + } else if (0 == inAndOutType) { + --num; + } + } + resultMap.put(key, num); + }); + + if (resultMap.size() != configMap.size()) { + return; + } + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + + // TODO: 2022/8/5 各时段人数统计 + //根据当前时间判断,每小时保存一次人数信息 + + return; + + } + + /** + * 今日访客量计算定时任务 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void visitorNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.apply("date_format(now(),'%Y-%m-%d') = date_format(in_time,'%Y-%m-%d')"); + List visitInfos = visitInfoMapper.selectList(wrapper); + HashMap resultMap = new HashMap<>(); + resultMap.put("今日访客量", visitInfos.size()); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 计算设备总数及在线率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void deviceNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + Integer total = deviceInfoMapper.selectCount(wrapper); + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("status", 1); //字典值:在线1、离线2、故障3 + Integer online = deviceInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) online / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("设备总数", total); + resultMap.put("设备在线率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 安保人员总数及安保人员离岗率 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void SecurityPersonNumber() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("staff_type", 2); + Integer total = staffInfoMapper.selectCount(wrapper); + //当日离岗事件个数 + QueryWrapper wrapper1 = new QueryWrapper<>(); + wrapper1.eq("hik_event_type", SecurityEventType.PERSONNEL_DEMOBILIZED_EVENT); + wrapper1.apply("date_format(now(),'%Y-%m-%d') = date_format(happen_time,'%Y-%m-%d')"); + Integer leave = caseInfoMapper.selectCount(wrapper1); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + String result = numberFormat.format((float) leave / (float) total * 100); + HashMap resultMap = new HashMap<>(); + resultMap.put("安保人员总数", total); + resultMap.put("安保人员离岗率", result+"%"); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 访客预约详情,按照访客访问目的字典进行分组,计算占总数的占比 + */ + @Scheduled(cron = "0 0/1 * * * ?") + public void VisitorApplyDetail() { + List reasonGroup = applyMapper.selectByVisitReason(); + HashMap resultMap = new HashMap<>(); + NumberFormat numberFormat = NumberFormat.getInstance(); + // 设置精确到小数点后2位 + numberFormat.setMaximumFractionDigits(2); + long sum = reasonGroup.stream().collect(Collectors.summarizingInt(ApplyReasonGroupDTO::getQuantity)).getSum(); + reasonGroup.forEach(group -> { + String reasonName = dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, group.getVisitReason()); + String result = numberFormat.format((float) group.getQuantity() / (float) sum * 100); + resultMap.put(reasonName, result+"%"); + }); + //websocket推送 + webSocket.sendAllMessage(JSONObject.toJSONString(resultMap)); + } + + /** + * 机动力量实时在岗率,在岗人数除以总应在岗人数,功能待定 + */ +// @Scheduled(cron = "0 0/1 * * * ?") + public void BeOnDutyRatio() { + + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java new file mode 100644 index 0000000..c4ca3f1 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/AttendanceInfo.java @@ -0,0 +1,33 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 考勤记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 16:50 + */ +@Data +@TableName("bus_attendance_info") +public class AttendanceInfo { + @TableId + private Long id; + private String staffCode; + private String staffName; + private String staffGender; + private String staffType; + @TableField(exist = false) + private String staffTypeName; + private String atteDate; + private String atteStartTime; + private String atteEndTime; + private String atteStartDev; + private String atteStartDevName; + private String atteEndDev; + private String atteEndDevName; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java index d2628fc..cb6b169 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/CaseInfo.java @@ -64,6 +64,8 @@ private String isKeyAreaName; @ExcelProperty("发生时间") private String happenTime; + //海康事件编码 + private Long hikEventType; private String createTime; private String updateTime; } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java index a04c350..66300db 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/DeviceInfo.java @@ -34,6 +34,8 @@ private String devName; @ExcelProperty("设备编号") private String devCode; + @ExcelProperty("海康设备编号") + private String indexCode; @ExcelProperty("设备类型") private String devType; //4个楼,字典值 diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java index 0c5e2d0..f9cbe78 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/StaffInfo.java @@ -32,6 +32,7 @@ private Long id; @ExcelProperty("员工编号") private String staffCode; + private String staffFaceId; @ExcelProperty("姓名") private String staffName; @ExcelProperty("性别") diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java new file mode 100644 index 0000000..b109813 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitInfo.java @@ -0,0 +1,31 @@ +package com.casic.missiles.modular.model; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @Description: 访客记录表实体 + * @Author: wangpeng + * @Date: 2022/7/28 19:35 + */ +@Data +@TableName("bus_visit_info") +public class VisitInfo { + @TableId + private Long id; + private String visitorName; + private String visitorGender; + private String idCard; + private String visitorPhone; + private String visitReason; + private String visitPosition; + private String inType; + private String orderId; + private String picUri; + private String serverIndexCode; + private String inTime; + private String outTime; + private String createTime; + private String updateTime; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java index 43b1ea4..6b35150 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/model/VisitorApply.java @@ -39,8 +39,8 @@ private String visitorPhone; @ExcelProperty("访问目的") private String visitReason; - @ExcelProperty("访问区域") - private String visitArea; + @ExcelProperty("访问楼栋") + private String visitPosition; @ExcelProperty("备注") private String remarks; @ExcelProperty("状态") @@ -57,12 +57,14 @@ private String outTime; //海康预约记录id private String appointRecordId; - //海康被访人唯一标识 - private String receptionistId; + //海康被访人唯一标识,即被访人工号 +// private String receptionistId; //访客记录唯一标识,用于已预约登记、访客签离等操作 - private String OrderId; - //访客头像,返回图片的相对Uri + private String orderId; + //访客头像,前端传base64,数据库存海康返回图片的相对Uri private String picUri; + //海康图片服务器唯一标识 + private String serverIndexCode; private String createTime; private String updateTime; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..3260a77 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.modular.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java new file mode 100644 index 0000000..07bb748 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.modular.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java new file mode 100644 index 0000000..be90e46 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.modular.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java new file mode 100644 index 0000000..564e942 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.modular.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String MONTH_STATISTIC_KEY = "missiles:cockpit:keyArea:monthStatistic"; +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java new file mode 100644 index 0000000..1560446 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/AttendanceService.java @@ -0,0 +1,16 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.model.AttendanceInfo; + +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +public interface AttendanceService { + List attendanceInfoListPage(Page page, StaffInfoRequest staffInfoRequest); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java index 55a1d4a..d96da4e 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/CaseInfoService.java @@ -18,4 +18,6 @@ int updateStatus(CaseInfoRequest caseInfoRequest); List addCaseInfoBatch(List results); + + boolean insertCaseInfoBatch(List caseInfos); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java index f345ff3..0647185 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/DeviceInfoService.java @@ -45,4 +45,6 @@ Object deleteGateGroupDTO(GateGroupDTO gateGroupDTO); List selectDeviceCodesByIds(List ids); + + List selectIndexCodesByCodes(List deviceCodes); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java new file mode 100644 index 0000000..dd24101 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/HikService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.service; + +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.modular.model.CaseInfo; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +public interface HikService { + + CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo); + + CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo); + + void propertyAttendanceHandle(JSONObject event); + + void securityPersonnelHandle(JSONObject event); + + void visitorRegisterHandler(JSONObject event); + + void visitorCheckOutHandler(JSONObject event); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java new file mode 100644 index 0000000..b7ebe90 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/VisitService.java @@ -0,0 +1,18 @@ +package com.casic.missiles.modular.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.model.VisitInfo; + +import java.util.List; + +/** + * @Description: 访客记录service + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +public interface VisitService { + List visitInfoListPage(Page page, VisitorRequest visitorRequest); + + VisitInfo visitInfoDetail(String id); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java index 28d66d9..e2fea95 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AssetInfoServiceImpl.java @@ -6,6 +6,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.AssetInfoMapper; import com.casic.missiles.modular.dto.AssetInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.AssetInfo; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.AssetInfoService; @@ -43,7 +44,7 @@ try { List pageList = assetInfoMapper.getAssetInfoListPage(page, assetInfoRequest); pageList.forEach(assetInfo ->{ - assetInfo.setAssetTypeName(dictService.getDictNameByCode("assetType", assetInfo.getAssetType())); + assetInfo.setAssetTypeName(dictService.getDictNameByCode(SecurityEventDict.ASSET_TYPE, assetInfo.getAssetType())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..df56fcb --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,44 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dto.StaffInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.AttendanceInfo; +import com.casic.missiles.modular.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 17:00 + */ +@Service +public class AttendanceServiceImpl extends ServiceImpl implements AttendanceService { + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List attendanceInfoListPage(Page page, StaffInfoRequest attendanceInfoRequest) { + try { + List pageList = attendanceInfoMapper.getAttendanceInfoListPage(page, attendanceInfoRequest); + pageList.forEach(attendanceInfo ->{ + attendanceInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, attendanceInfo.getStaffType())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("考勤: 查询分页出现异常, 异常:{}", ex); + } + return null; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java index 1b8ac75..8f47b37 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/BlackInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.casic.missiles.modular.dto.hik.FacePic; import com.casic.missiles.modular.dto.hik.FaceSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.BlackInfo; import com.casic.missiles.modular.model.HikFaceGroupInfo; import com.casic.missiles.modular.service.BlackInfoService; @@ -52,7 +53,7 @@ try { List pageList = blackInfoMapper.getBlackInfoListPage(page, blackInfoRequest); pageList.forEach(blackInfo ->{ - blackInfo.setBlackReasonName(dictService.getDictNameByCode("blackReason", blackInfo.getBlackReason())); + blackInfo.setBlackReasonName(dictService.getDictNameByCode(SecurityEventDict.BLACK_REASON, blackInfo.getBlackReason())); }); return pageList; } catch (DataAccessException ex) { @@ -87,8 +88,8 @@ } JSONObject dataJson = (JSONObject)resultJson.get("data"); //设置海康人脸唯一标识、人脸分组唯一标识 - blackInfo.setIndexCode((String) dataJson.get("indexCode")); - blackInfo.setFaceGroupIndexCode((String) dataJson.get("faceGroupIndexCode")); + blackInfo.setIndexCode(String.valueOf(dataJson.get("indexCode"))); + blackInfo.setFaceGroupIndexCode(String.valueOf(dataJson.get("faceGroupIndexCode"))); //保存图片到本地 String picUrl = fileService.saveFile(blackInfo.getPicture()); blackInfo.setPicture(picUrl); diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java index d1057e5..6fa536c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/CaseInfoServiceImpl.java @@ -7,6 +7,7 @@ import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.modular.dao.CaseInfoMapper; import com.casic.missiles.modular.dto.CaseInfoRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.service.CaseInfoService; import lombok.extern.slf4j.Slf4j; @@ -45,10 +46,10 @@ try { List pageList = caseInfoMapper.getCaseInfoListPage(page, caseInfoRequest); pageList.forEach(caseInfo ->{ - caseInfo.setStatusName(dictService.getDictNameByCode("caseStatus", caseInfo.getStatus())); - caseInfo.setPositionName(dictService.getDictNameByCode("devicePosition", caseInfo.getPosition())); - caseInfo.setAreaName(dictService.getDictNameByCode("deviceArea", caseInfo.getArea())); - caseInfo.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", caseInfo.getIsKeyArea())); + caseInfo.setStatusName(dictService.getDictNameByCode(SecurityEventDict.CASE_STATUS, caseInfo.getStatus())); + caseInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, caseInfo.getPosition())); + caseInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, caseInfo.getArea())); + caseInfo.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, caseInfo.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -108,4 +109,9 @@ } return list; } + + @Override + public boolean insertCaseInfoBatch(List caseInfos) { + return this.saveBatch(caseInfos); + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java index 849e4f1..9d9c731 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/DeviceInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dao.GateGroupMapper; import com.casic.missiles.modular.dao.GroupDeviceMapper; import com.casic.missiles.modular.dto.*; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.DeviceRepairLog; import com.casic.missiles.modular.model.GateGroup; @@ -68,11 +69,11 @@ try { List pageList = deviceInfoMapper.getDeviceInfoListPage(page, deviceInfoRequest); pageList.forEach(device ->{ - device.setDevType(dictService.getDictNameByCode("deviceType", device.getDevType())); - device.setStatus(dictService.getDictNameByCode("deviceStatus", device.getStatus())); - device.setPositionName(dictService.getDictNameByCode("devicePosition", device.getPosition())); - device.setAreaName(dictService.getDictNameByCode("deviceArea", device.getArea())); - device.setIsKeyAreaName(dictService.getDictNameByCode("IsKeyArea", device.getIsKeyArea())); + device.setDevType(dictService.getDictNameByCode(SecurityEventDict.DEVICE_TYPE, device.getDevType())); + device.setStatus(dictService.getDictNameByCode(SecurityEventDict.DEVICE_STATUS, device.getStatus())); + device.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, device.getPosition())); + device.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, device.getArea())); + device.setIsKeyAreaName(dictService.getDictNameByCode(SecurityEventDict.IS_KEY_AREA, device.getIsKeyArea())); }); return pageList; } catch (DataAccessException ex) { @@ -214,7 +215,7 @@ try { List pageList = gateGroupMapper.getGateGroupListPage(page, gateGroupRequest); pageList.forEach(gateGroup ->{ - gateGroup.setStatusName(dictService.getDictNameByCode("groupDeviceStatus", gateGroup.getStatus())); + gateGroup.setStatusName(dictService.getDictNameByCode(SecurityEventDict.GROUP_DEVICE_STATUS, gateGroup.getStatus())); }); return pageList; } catch (DataAccessException ex) { @@ -300,5 +301,11 @@ return deviceCodes; } + @Override + public List selectIndexCodesByCodes(List deviceCodes) { + List indexCodes = deviceInfoMapper.selectIndexCodesByCodes(deviceCodes); + return indexCodes; + } + } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java index 8a5f370..a95fff2 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/FireEquipServiceImpl.java @@ -8,6 +8,7 @@ import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.dao.FireEquipInfoMapper; import com.casic.missiles.modular.dto.FireEquipRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.FireEquipInfo; import com.casic.missiles.modular.service.FireEquipService; @@ -48,10 +49,10 @@ try { List pageList = fireEquipInfoMapper.getFireEquipInfoListPage(page, fireEquipRequest); pageList.forEach(equipInfo ->{ - equipInfo.setEquipTypeName(dictService.getDictNameByCode("equipType", equipInfo.getEquipType())); - equipInfo.setFireLevelName(dictService.getDictNameByCode("fireLevel", equipInfo.getFireLevel())); - equipInfo.setPositionName(dictService.getDictNameByCode("devicePosition", equipInfo.getPosition())); - equipInfo.setAreaName(dictService.getDictNameByCode("deviceArea", equipInfo.getArea())); + equipInfo.setEquipTypeName(dictService.getDictNameByCode(SecurityEventDict.EQUIP_TYPE, equipInfo.getEquipType())); + equipInfo.setFireLevelName(dictService.getDictNameByCode(SecurityEventDict.FIRE_LEVEL, equipInfo.getFireLevel())); + equipInfo.setPositionName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, equipInfo.getPosition())); + equipInfo.setAreaName(dictService.getDictNameByCode(SecurityEventDict.DEVICE_AREA, equipInfo.getArea())); }); return pageList; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java new file mode 100644 index 0000000..b47f78f --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/HikServiceImpl.java @@ -0,0 +1,284 @@ +package com.casic.missiles.modular.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.AttendanceInfoMapper; +import com.casic.missiles.modular.dao.DeviceInfoMapper; +import com.casic.missiles.modular.dao.StaffInfoMapper; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.*; +import com.casic.missiles.modular.service.HikService; +import com.casic.missiles.modular.system.model.Dict; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 13:59 + */ +@Slf4j +@Service +public class HikServiceImpl implements HikService { + + @Resource + private AbstractDictService dictService; + + @Autowired + private StaffInfoMapper staffInfoMapper; + + @Autowired + private AttendanceInfoMapper attendanceInfoMapper; + + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Autowired + private DeviceInfoMapper deviceInfoMapper; + + @Override + public CaseInfo blackListHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo demobilizedHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo personGatherHandle(JSONObject event, CaseInfo caseInfo) { + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + return caseInfo; + } + + @Override + public CaseInfo monitorPointOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public CaseInfo deviceOfflineHandle(JSONObject event, CaseInfo caseInfo) { + //加入到安防事件 + String srcIndex = event.getString("srcIndex"); //海康资源唯一标识 + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + caseInfo.setHappenTime(happenTime); //发生时间 + // TODO: 2022/7/28 字典值选择 + List dict = dictService.findInDictByCode(SecurityEventDict.CASE_STATUS); + caseInfo.setStatus(dict.get(0).getCode()); //事件状态(未解决的字典值) + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + caseInfo.setDeviceCode(deviceInfo.getDevCode()); //设备code + caseInfo.setDevName(deviceInfo.getDevName()); //设备名 + caseInfo.setPosition(deviceInfo.getPosition()); //事件位置 + caseInfo.setArea(deviceInfo.getArea()); //区域 + //更新设备状态 + // TODO: 2022/7/28 设备离线字典值选择 +// deviceInfo.setStatus(); + if(deviceInfoMapper.updateById(deviceInfo) <= 0){ + return null; + } + return caseInfo; + } + + @Override + public void propertyAttendanceHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 物业人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增物业人员考勤异常"); + return; + } + } + } + + @Override + public void securityPersonnelHandle(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + JSONObject faceRecognitionResult = (JSONObject) data.get("faceRecognitionResult"); + JSONArray faceMatchArr = (JSONArray) faceRecognitionResult.get("faceMatch"); + JSONObject faceMatch = (JSONObject) faceMatchArr.get(0); + String faceInfoCode = faceMatch.getString("faceInfoCode"); + String happenTimeISO = String.valueOf(event.get("happenTime")); + DateTime parse = DateUtil.parse(happenTimeISO); + String happenTime = DateUtil.formatDateTime(parse); + //使用海康人脸唯一标识获取员工信息 + Map columnMap = new HashMap<>(); + columnMap.put("staff_face_id", faceInfoCode); + List staffInfos = staffInfoMapper.selectByMap(columnMap); + StaffInfo staffInfo = staffInfos.get(0); + //存储考勤信息 + //存在当天考勤则更新离开时间 + AttendanceInfo attendanceInfo = attendanceInfoMapper.selectByCodeAndDate(staffInfo.getStaffCode()); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + if(!Objects.isNull(attendanceInfo)){ + attendanceInfo.setAtteEndTime(happenTime); + attendanceInfo.setAtteEndDev(deviceInfo.getDevCode()); + attendanceInfo.setAtteEndDevName(deviceInfo.getDevName()); + return; + }else{ + AttendanceInfo info = new AttendanceInfo(); + info.setStaffCode(staffInfo.getStaffCode()); + info.setStaffName(staffInfo.getStaffName()); + info.setStaffGender(staffInfo.getStaffGender()); + // TODO: 2022/7/29 安保人员字典值选择 +// info.setStaffType(); +// info.setStaffTypeName(); + info.setAtteDate(DateUtil.today()); + info.setAtteStartTime(happenTime); + info.setAtteStartDev(deviceInfo.getDevCode()); + info.setAtteStartDevName(deviceInfo.getDevName()); + if(attendanceInfoMapper.insert(info) <= 0){ + log.error("新增安保人员考勤异常"); + return; + } + } + } + + @Override + public void visitorRegisterHandler(JSONObject event) { + String srcIndex = event.getString("srcIndex"); + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("startTime")); + String startTime = DateUtil.formatDateTime(parse); + DeviceInfo deviceInfo = deviceInfoMapper.getByIndexCode(srcIndex); + VisitInfo visitInfo = new VisitInfo(); + visitInfo.setVisitorName(data.getString("personName")); + visitInfo.setVisitorGender(data.getString("sex")); + visitInfo.setVisitorPhone(data.getString("phone")); + visitInfo.setInTime(startTime); //来访时间 +// visitInfo.setOutTime(); + if("111".equals(data.getString("idType"))){ + visitInfo.setInType("身份证"); + visitInfo.setIdCard(data.getString("idNo")); + } + visitInfo.setVisitReason(data.getString("purpose")); + visitInfo.setPicUri(data.getString("captureUrl")); + visitInfo.setServerIndexCode(data.getString("svrIndexCode")); + visitInfo.setVisitPosition(deviceInfo.getPosition()); + + if(visitInfoMapper.insert(visitInfo) <= 0){ + log.error("新增访客记录异常"); + } + } + + @Override + public void visitorCheckOutHandler(JSONObject event) { + JSONObject data = (JSONObject) event.get("data"); + DateTime parse = DateUtil.parse(data.getString("endTime")); + String endTime = DateUtil.formatDateTime(parse); + VisitInfo visitInfo = visitInfoMapper.selectByOrderId(data.getString("visitorId")); + if(!Objects.isNull(visitInfo)){ + visitInfo.setOutTime(endTime); + } + if(visitInfoMapper.updateById(visitInfo) <= 0){ + log.error("更新访客记录异常"); + } + } + + +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java index 207b95c..b416f5c 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/StaffInfoServiceImpl.java @@ -11,6 +11,7 @@ import com.casic.missiles.modular.dto.hik.PersonBatchDeleteRequest; import com.casic.missiles.modular.dto.hik.PersonSingleAddOrUpdateRequest; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; import com.casic.missiles.modular.model.DeviceInfo; import com.casic.missiles.modular.model.StaffInfo; import com.casic.missiles.modular.service.StaffInfoService; @@ -61,7 +62,7 @@ try { List pageList = staffInfoMapper.getStaffInfoListPage(page, staffInfoRequest); pageList.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); String base64 = Base64Util.transformPictureToBase64(uploadPath + staffInfo.getPicture()); staffInfo.setPicture(base64); }); @@ -104,6 +105,9 @@ log.error("请求海康,单个添加人员失败,海康response:{}", resultStr); return ResponseData.error("单个添加人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.insert(staffInfo) > 0){ return ResponseData.success(); } @@ -138,6 +142,9 @@ log.error("请求海康,单个修改人员失败,海康response:{}", resultStr); return ResponseData.error("单个修改人员失败"); } + JSONObject data = (JSONObject)resultJson.get("data"); + String faceId = data.getString("faceId"); + staffInfo.setStaffFaceId(faceId); if(staffInfoMapper.updateById(staffInfo) > 0){ return ResponseData.success(); } @@ -254,7 +261,7 @@ try { List list = staffInfoMapper.getStaffInfoList(staffInfoRequest); list.forEach(staffInfo -> { - staffInfo.setStaffTypeName(dictService.getDictNameByCode("staffType", staffInfo.getStaffType())); + staffInfo.setStaffTypeName(dictService.getDictNameByCode(SecurityEventDict.STAFF_TYPE, staffInfo.getStaffType())); }); return list; } catch (DataAccessException ex) { diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java new file mode 100644 index 0000000..39618ea --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitServiceImpl.java @@ -0,0 +1,53 @@ +package com.casic.missiles.modular.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.core.application.service.AbstractDictService; +import com.casic.missiles.modular.dao.VisitInfoMapper; +import com.casic.missiles.modular.dto.VisitorRequest; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.VisitInfo; +import com.casic.missiles.modular.service.VisitService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 19:40 + */ +@Slf4j +@Service +public class VisitServiceImpl extends ServiceImpl implements VisitService { + @Autowired + private VisitInfoMapper visitInfoMapper; + + @Resource + private AbstractDictService dictService; + + @Override + public List visitInfoListPage(Page page, VisitorRequest visitorRequest) { + try { + List pageList = visitInfoMapper.getVisitInfoListPage(page, visitorRequest); + pageList.forEach(visitInfo ->{ + visitInfo.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitInfo.getVisitReason())); + visitInfo.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitInfo.getVisitPosition())); + }); + return pageList; + } catch (DataAccessException ex) { + log.error("访客: 查询分页出现异常,异常:{}", ex); + } + return null; + } + + @Override + public VisitInfo visitInfoDetail(String id) { + VisitInfo visitInfo = visitInfoMapper.selectById(id); + return visitInfo; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java index d9fa377..1f3f89b 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/service/impl/VisitorApplyServiceImpl.java @@ -1,7 +1,9 @@ package com.casic.missiles.modular.service.impl; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -11,16 +13,27 @@ import com.casic.missiles.modular.dto.hik.AppointmentFreeRegisterRequest; import com.casic.missiles.modular.dto.hik.VisitorInfo; import com.casic.missiles.modular.enums.HikUri; +import com.casic.missiles.modular.enums.SecurityEventDict; +import com.casic.missiles.modular.model.CaseInfo; import com.casic.missiles.modular.model.VisitorApply; import com.casic.missiles.modular.service.VisitorApplyService; import com.casic.missiles.modular.util.HikUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.validation.BeanPropertyBindingResult; +import org.springframework.validation.FieldError; +import org.springframework.validation.Validator; import javax.annotation.Resource; +import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * @Description: @@ -36,12 +49,16 @@ @Resource private AbstractDictService dictService; + @Resource + private Validator validator; + @Override public List visitorApplyListPage(Page page, VisitorApplyRequest visitorApplyRequest) { try { List pageList = visitorApplyMapper.getVisitorApplyListPage(page, visitorApplyRequest); pageList.forEach(visitorApply ->{ - visitorApply.setVisitReason(dictService.getDictNameByCode("visitReason", visitorApply.getVisitReason())); + visitorApply.setVisitReason(dictService.getDictNameByCode(SecurityEventDict.VISIT_REASON, visitorApply.getVisitReason())); + visitorApply.setVisitPosition(dictService.getDictNameByCode(SecurityEventDict.DEVICE_POSITION, visitorApply.getVisitPosition())); }); return pageList; } catch (DataAccessException ex) { @@ -51,17 +68,17 @@ } @Override + @Transactional(rollbackFor = Exception.class) public int addVisitorApply(VisitorApply visitorApply) { - // TODO: 2022/7/26 数据重复处理 + //无需判重,可预约多个时间段 AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); - // TODO: 2022/7/25 ReceptionistId由前端传,数据源自海康,需考虑海康员工唯一标识与我们唯一标识对应问题 //将时间转换为海康ISO8601格式 DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); - - appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getReceptionistId()); + //海康员工唯一标识receptionistId就是我们录入的到海康的员工号 + appointmentFreeRegisterRequest.setReceptionistId(visitorApply.getStaffCode()); appointmentFreeRegisterRequest.setPersonNum(1); appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); @@ -73,6 +90,7 @@ visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); visitorInfo.setCertificateNo(visitorApply.getIdCard()); visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); @@ -82,26 +100,191 @@ log.error("请求海康,预约免登记失败,海康response:{}", resultStr); return 0; } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); return visitorApplyMapper.insert(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int updateVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + //修改海康访客预约 + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setAppointRecordId(visitorApply1.getAppointRecordId()); + appointmentFreeRegisterRequest.setReceptionistId(visitorApply1.getStaffCode()); + DateTime inTimeDate = DateUtil.parse(visitorApply.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(visitorApply.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(visitorApply.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(visitorApply.getVisitorName()); + visitorInfo.setGender(visitorApply.getVisitorGender()); + visitorInfo.setPhoneNo(visitorApply.getVisitorPhone()); + visitorInfo.setCertificateNo(visitorApply.getIdCard()); + visitorInfo.setCertificateType(111); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorInfo.setVisitorPhoto(visitorApply.getPicUri()); + } + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + + String body = JSONObject.toJSONString(appointmentFreeRegisterRequest); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_UPDATE, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,修改访客预约失败,海康response:{}", resultStr); + return 0; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + String svrIndexCode = String.valueOf(jsonData.get("svrIndexCode")); + visitorApply.setAppointRecordId(appointRecordId); + visitorApply.setOrderId(orderId); + if(StringUtils.isNotEmpty(visitorApply.getPicUri())){ + visitorApply.setPicUri(picUri); + visitorApply.setServerIndexCode(svrIndexCode); + } return visitorApplyMapper.updateById(visitorApply); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteVisitorApply(VisitorApply visitorApply) { + VisitorApply visitorApply1 = visitorApplyMapper.selectById(visitorApply.getId()); + if(StringUtils.isNotEmpty(visitorApply1.getAppointRecordId())){ + List appointRecordIds = new ArrayList<>(); + appointRecordIds.add(visitorApply.getAppointRecordId()); + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("该访客:{},未在海康进行预约成功,无法取消预约", visitorApply.getVisitorName()); + return 0; + } return visitorApplyMapper.deleteById(visitorApply.getId()); } @Override + @Transactional(rollbackFor = Exception.class) public int deleteBatchVisitorApply(List ids) { + List visitorApplies = visitorApplyMapper.selectBatchIds(ids); + List appointRecordIds = visitorApplies.stream().map(VisitorApply::getAppointRecordId).collect(Collectors.toList()); + if(!CollectionUtils.isEmpty(appointRecordIds)){ + String body = JSONObject.toJSONString(appointRecordIds); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_CANCEL, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,批量取消访客预约失败,海康response:{}", resultStr); + return 0; + } + }else{ + log.error("访客列表:{},未在海康进行预约成功,无法取消预约", appointRecordIds); + return 0; + } return deleteBatchVisitorApply(ids); } @Override public List addVisitorApplyBatch(List results) { - return null; + BeanPropertyBindingResult beanPropertyBindingResult = new BeanPropertyBindingResult(CaseInfo.class, "访客申请导入校验"); + List list = new ArrayList<>(); + if (!CollectionUtil.isEmpty(results)) { + final Integer[] index = {0}; + List appointList = new ArrayList<>(); + results.forEach(busConcentrator -> { + validator.validate(busConcentrator, beanPropertyBindingResult); + index[0]++; + if (beanPropertyBindingResult.hasErrors()) { + List errors = beanPropertyBindingResult.getFieldErrors(); + errors.forEach(error -> { + list.add(" 第" + index[0] + "行,".concat(error.getDefaultMessage())); + return; + } + ); + return; + } + if (StrUtil.isNotEmpty(busConcentrator.getInTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getInTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + if (StrUtil.isNotEmpty(busConcentrator.getOutTime())) { + try { + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(busConcentrator.getOutTime()); + } catch (Exception e) { + list.add(" 第" + index[0] + "行,时间格式不正确"); + return; + } + } + DateTime inTimeDate = DateUtil.parse(busConcentrator.getInTime()); + String inTimeISODate = DateUtil.format(inTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + DateTime outTimeDate = DateUtil.parse(busConcentrator.getOutTime()); + String outTimeISODate = DateUtil.format(outTimeDate, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + AppointmentFreeRegisterRequest appointmentFreeRegisterRequest = new AppointmentFreeRegisterRequest(); + appointmentFreeRegisterRequest.setReceptionistId(busConcentrator.getStaffCode()); + appointmentFreeRegisterRequest.setPersonNum(1); + appointmentFreeRegisterRequest.setVisitStartTime(inTimeISODate); + appointmentFreeRegisterRequest.setVisitEndTime(outTimeISODate); + appointmentFreeRegisterRequest.setVisitPurpose(busConcentrator.getVisitReason()); + VisitorInfo visitorInfo = new VisitorInfo(); + visitorInfo.setVisitorName(busConcentrator.getVisitorName()); + visitorInfo.setGender(busConcentrator.getVisitorGender()); + visitorInfo.setPhoneNo(busConcentrator.getVisitorPhone()); + visitorInfo.setCertificateNo(busConcentrator.getIdCard()); + visitorInfo.setCertificateType(111); + visitorInfo.setVisitorPhoto(busConcentrator.getPicUri()); + appointmentFreeRegisterRequest.setVisitorInfo(visitorInfo); + appointList.add(appointmentFreeRegisterRequest); + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + appointList.forEach(app -> { + String body = JSONObject.toJSONString(app); + String resultStr = HikUtil.hikApi(HikUri.APPOINTMENT_FREE_REGISTER, body); + JSONObject resultJson = (JSONObject)JSONObject.parse(resultStr); + if(!"0".equals(resultJson.get("code"))){ + log.error("请求海康,预约免登记失败,海康response:{}", resultStr); + list.add("请求海康,预约免登记失败,访客姓名:"+app.getVisitorInfo().getVisitorName()); + return; + } + JSONObject jsonData = (JSONObject)resultJson.get("data"); + String appointRecordId = String.valueOf(jsonData.get("appointRecordId")); + String orderId = String.valueOf(jsonData.get("orderId")); + String picUri = String.valueOf(jsonData.get("picUri")); + for (VisitorApply result : results) { + //身份证判断同一访客,设置访客信息 + if(result.getIdCard().equals(app.getVisitorInfo().getCertificateNo())){ + result.setAppointRecordId(appointRecordId); + result.setOrderId(orderId); + result.setPicUri(picUri); + } + } + }); + if (CollectionUtil.isNotEmpty(list)) { + return list; + } + this.saveBatch(results); + } + return list; } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java new file mode 100644 index 0000000..511f014 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/util/ThreadPoolUtil.java @@ -0,0 +1,24 @@ +package com.casic.missiles.modular.util; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/7/28 11:09 + */ +@Slf4j +@Component +public class ThreadPoolUtil { + public static ExecutorService executorService; + + @PostConstruct + public void initExecutorService() { + executorService = Executors.newFixedThreadPool(10); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java b/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java index 9b4155c..5c7f422 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/util/WebSocket.java @@ -1,5 +1,6 @@ package com.casic.missiles.modular.util; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.websocket.OnClose; @@ -18,6 +19,7 @@ * @Author: wangpeng * @Date: 2022/7/17 11:48 */ +@Slf4j @Component @ServerEndpoint("/websocket/{userId}") public class WebSocket { @@ -31,27 +33,32 @@ this.session = session; webSockets.add(this); sessionPool.put(userId, session); - System.out.println(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); + log.info(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); +// System.out.println(userId + "【websocket消息】有新的连接,总数为:" + webSockets.size()); } @OnClose public void onClose() { webSockets.remove(this); - System.out.println("【websocket消息】连接断开,总数为:" + webSockets.size()); + log.info("【websocket消息】连接断开,总数为:" + webSockets.size()); +// System.out.println("【websocket消息】连接断开,总数为:" + webSockets.size()); } @OnMessage public void onMessage(String message) { - System.out.println("【websocket消息】收到客户端消息:" + message); + log.info("【websocket消息】收到客户端消息:" + message); +// System.out.println("【websocket消息】收到客户端消息:" + message); } // 此为广播消息 public void sendAllMessage(String message) { for (WebSocket webSocket : webSockets) { - System.out.println("【websocket消息】广播消息:" + message); + log.info("【websocket消息】广播消息:" + message); +// System.out.println("【websocket消息】广播消息:" + message); try { webSocket.session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】广播消息发送异常"); e.printStackTrace(); } } @@ -59,44 +66,31 @@ // 发送列表消息 public void sendListMessage(List userIds, String message) { - System.out.println("【websocket消息】列表消息:" + message); + log.info("【websocket消息】列表消息:" + message); +// System.out.println("【websocket消息】列表消息:" + message); for (String userId : userIds) { Session session = sessionPool.get(userId); if (session != null) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】列表消息发送异常"); e.printStackTrace(); } } } } - // 发送列表消息 - -// public void sendListMessage(List userIds, Object data){ -// System.out.println("【websocket消息】列表消息:"+data); -// for (String userId : userIds) { -// Session session = sessionPool.get(userId); -// if (session != null) { -// try { -//// session.getAsyncRemote().sendText(message); -// session.getAsyncRemote().sendObject(data); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } -// } -// } - // 此为单点消息 public void sendOneMessage(String userId, String message) { - System.out.println("【websocket消息】单点消息:" + message); + log.info("【websocket消息】单点消息:" + message); +// System.out.println("【websocket消息】单点消息:" + message); Session session = sessionPool.get(userId); if (session != null) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { + log.error("【websocket消息】单点消息发送异常"); e.printStackTrace(); } } diff --git a/casic-web/pom.xml b/casic-web/pom.xml index 53f549f..12786de 100644 --- a/casic-web/pom.xml +++ b/casic-web/pom.xml @@ -56,6 +56,10 @@ org.springframework.boot spring-boot-starter-jdbc + + org.springframework.boot + spring-boot-starter-data-redis + com.casic diff --git a/casic-web/src/main/build/bin/start.sh b/casic-web/src/main/build/bin/start.sh index c00b1ef..562149f 100644 --- a/casic-web/src/main/build/bin/start.sh +++ b/casic-web/src/main/build/bin/start.sh @@ -1,2 +1 @@ -java -jar ./lib/${project.build.finalName}.jar - +java -jar ./lib/${project.build.finalName}.jar \ No newline at end of file diff --git a/casic-web/src/main/build/bin/teststart.sh b/casic-web/src/main/build/bin/teststart.sh new file mode 100644 index 0000000..d737e70 --- /dev/null +++ b/casic-web/src/main/build/bin/teststart.sh @@ -0,0 +1 @@ +nohup java -jar ./lib/${project.build.finalName}.jar > /dev/null 2>&1 & \ No newline at end of file diff --git a/casic-web/src/main/build/package.xml b/casic-web/src/main/build/package.xml index c9259ad..394dd0f 100644 --- a/casic-web/src/main/build/package.xml +++ b/casic-web/src/main/build/package.xml @@ -8,6 +8,7 @@ true + true true diff --git a/casic-web/src/main/resources/config/application-dev.yml b/casic-web/src/main/resources/config/application-dev.yml index 48b510b..4712961 100644 --- a/casic-web/src/main/resources/config/application-dev.yml +++ b/casic-web/src/main/resources/config/application-dev.yml @@ -1,5 +1,5 @@ server: - port: 18083 + port: 5903 ################### spring配置 ################### spring: datasource: @@ -7,6 +7,12 @@ url: jdbc:mysql://111.198.10.15:11336/casic_security_cockpit?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true username: root password: Casic203 + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer jms: pub-sub-domain: true # session: @@ -31,4 +37,13 @@ logging: level.root: info level.com.casic: debug - level.org.springframework.web: info \ No newline at end of file + level.org.springframework.web: info + +#所属楼栋及各楼栋内门禁点列表配置 +#1/2/3/4对应字典中4个楼栋 +accessgroup: + configMap: + 1: [1,2,3] + 2: [2,3,4] + 3: [3,4,5] + 4: [4,5,6] \ No newline at end of file diff --git a/casic-web/src/main/resources/config/application-prod.yml b/casic-web/src/main/resources/config/application-prod.yml index f646180..0073ca8 100644 --- a/casic-web/src/main/resources/config/application-prod.yml +++ b/casic-web/src/main/resources/config/application-prod.yml @@ -1,5 +1,5 @@ server: - port: 18083 + port: 5903 # context-path: /callcenter/api ################### spring配置 ################### spring: diff --git a/casic-web/src/main/resources/config/application-test.yml b/casic-web/src/main/resources/config/application-test.yml index 0dbb1ed..fdfb535 100644 --- a/casic-web/src/main/resources/config/application-test.yml +++ b/casic-web/src/main/resources/config/application-test.yml @@ -1,5 +1,5 @@ server: - port: 18083 + port: 5903 ################### spring配置 ################### spring: datasource: