Browse Source

初始化

alan 2 years ago
commit
16124cabab
100 changed files with 7892 additions and 0 deletions
  1. 44 0
      .drone.yml
  2. 33 0
      .gitignore
  3. BIN
      .mvn/wrapper/maven-wrapper.jar
  4. 2 0
      .mvn/wrapper/maven-wrapper.properties
  5. 5 0
      Dockerfile
  6. 331 0
      mvnw
  7. 188 0
      mvnw.cmd
  8. 160 0
      pom.xml
  9. 68 0
      screen.yml
  10. 27 0
      src/main/java/com/zhili/dashboard/OmesDashboardApplication.java
  11. 16 0
      src/main/java/com/zhili/dashboard/annotation/RepeatSubmit.java
  12. 149 0
      src/main/java/com/zhili/dashboard/base/AjaxResult.java
  13. 29 0
      src/main/java/com/zhili/dashboard/base/BaseCycleChartVo.java
  14. 78 0
      src/main/java/com/zhili/dashboard/base/BaseEntity.java
  15. 23 0
      src/main/java/com/zhili/dashboard/base/BaseIntegerLineChartVo.java
  16. 24 0
      src/main/java/com/zhili/dashboard/base/BaseLineChartVo.java
  17. 23 0
      src/main/java/com/zhili/dashboard/base/BaseLineDecimalVo.java
  18. 213 0
      src/main/java/com/zhili/dashboard/base/Constants.java
  19. 16 0
      src/main/java/com/zhili/dashboard/base/HzTokenResponse.java
  20. 28 0
      src/main/java/com/zhili/dashboard/base/IdParam.java
  21. 22 0
      src/main/java/com/zhili/dashboard/base/KindValueDoubleListVo.java
  22. 21 0
      src/main/java/com/zhili/dashboard/base/KindValueListVo.java
  23. 73 0
      src/main/java/com/zhili/dashboard/base/LoginBody.java
  24. 264 0
      src/main/java/com/zhili/dashboard/base/LoginUser.java
  25. 27 0
      src/main/java/com/zhili/dashboard/base/PageParam.java
  26. 88 0
      src/main/java/com/zhili/dashboard/base/UserInfoVO.java
  27. 22 0
      src/main/java/com/zhili/dashboard/base/UserInformationDTO.java
  28. 72 0
      src/main/java/com/zhili/dashboard/config/FastJson2JsonRedisSerializer.java
  29. 124 0
      src/main/java/com/zhili/dashboard/config/HzConfig.java
  30. 43 0
      src/main/java/com/zhili/dashboard/config/MybatisPlusConfig.java
  31. 92 0
      src/main/java/com/zhili/dashboard/config/OkHttpConfiguration.java
  32. 28 0
      src/main/java/com/zhili/dashboard/config/PropertyConfig.java
  33. 79 0
      src/main/java/com/zhili/dashboard/config/RedisConfig.java
  34. 36 0
      src/main/java/com/zhili/dashboard/config/ResourcesConfig.java
  35. 31 0
      src/main/java/com/zhili/dashboard/config/SecurityConfig.java
  36. 135 0
      src/main/java/com/zhili/dashboard/config/SwaggerConfig.java
  37. 66 0
      src/main/java/com/zhili/dashboard/config/ThreadPoolConfig.java
  38. 173 0
      src/main/java/com/zhili/dashboard/controller/AlarmMsgController.java
  39. 19 0
      src/main/java/com/zhili/dashboard/controller/CommandController.java
  40. 32 0
      src/main/java/com/zhili/dashboard/controller/DeviceController.java
  41. 20 0
      src/main/java/com/zhili/dashboard/controller/DeviceDurationController.java
  42. 20 0
      src/main/java/com/zhili/dashboard/controller/OrgController.java
  43. 20 0
      src/main/java/com/zhili/dashboard/controller/StatisticsController.java
  44. 84 0
      src/main/java/com/zhili/dashboard/entity/AlarmMsg.java
  45. 83 0
      src/main/java/com/zhili/dashboard/entity/AlarmMsgWarn.java
  46. 47 0
      src/main/java/com/zhili/dashboard/entity/CmdDetail.java
  47. 36 0
      src/main/java/com/zhili/dashboard/entity/Command.java
  48. 82 0
      src/main/java/com/zhili/dashboard/entity/Device.java
  49. 37 0
      src/main/java/com/zhili/dashboard/entity/DeviceDuration.java
  50. 47 0
      src/main/java/com/zhili/dashboard/entity/DistributionMap.java
  51. 37 0
      src/main/java/com/zhili/dashboard/entity/FaultMonthRate.java
  52. 52 0
      src/main/java/com/zhili/dashboard/entity/Model.java
  53. 31 0
      src/main/java/com/zhili/dashboard/entity/Online.java
  54. 42 0
      src/main/java/com/zhili/dashboard/entity/Org.java
  55. 35 0
      src/main/java/com/zhili/dashboard/entity/Statistics.java
  56. 46 0
      src/main/java/com/zhili/dashboard/enums/AlarmCoreTypeEnum.java
  57. 46 0
      src/main/java/com/zhili/dashboard/enums/AlarmFaultStatusEnum.java
  58. 49 0
      src/main/java/com/zhili/dashboard/enums/AlarmLevelEnum.java
  59. 47 0
      src/main/java/com/zhili/dashboard/enums/AlarmLevelGroupEnum.java
  60. 47 0
      src/main/java/com/zhili/dashboard/enums/BatteryDataTypeEnum.java
  61. 51 0
      src/main/java/com/zhili/dashboard/enums/BatteryStatusEnum.java
  62. 48 0
      src/main/java/com/zhili/dashboard/enums/DeviceStatusEnum.java
  63. 49 0
      src/main/java/com/zhili/dashboard/enums/SceneEnum.java
  64. 177 0
      src/main/java/com/zhili/dashboard/gen/CodeGenerator.java
  65. 27 0
      src/main/java/com/zhili/dashboard/handler/ApplicationContextHolder.java
  66. 33 0
      src/main/java/com/zhili/dashboard/handler/AuthenticationEntryPointImpl.java
  67. 58 0
      src/main/java/com/zhili/dashboard/handler/CustomMetaObjectHandler.java
  68. 42 0
      src/main/java/com/zhili/dashboard/handler/JwtAuthenticationTokenFilter.java
  69. 52 0
      src/main/java/com/zhili/dashboard/handler/LogoutSuccessHandlerImpl.java
  70. 49 0
      src/main/java/com/zhili/dashboard/handler/RepeatSubmitInterceptor.java
  71. 163 0
      src/main/java/com/zhili/dashboard/mapper/AlarmMsgMapper.java
  72. 86 0
      src/main/java/com/zhili/dashboard/mapper/AlarmMsgWarnMapper.java
  73. 16 0
      src/main/java/com/zhili/dashboard/mapper/CmdDetailMapper.java
  74. 16 0
      src/main/java/com/zhili/dashboard/mapper/CommandMapper.java
  75. 16 0
      src/main/java/com/zhili/dashboard/mapper/DeviceDurationMapper.java
  76. 16 0
      src/main/java/com/zhili/dashboard/mapper/DeviceMapper.java
  77. 41 0
      src/main/java/com/zhili/dashboard/mapper/DistributionMapMapper.java
  78. 34 0
      src/main/java/com/zhili/dashboard/mapper/FaultMonthRateMapper.java
  79. 14 0
      src/main/java/com/zhili/dashboard/mapper/ModelMapper.java
  80. 24 0
      src/main/java/com/zhili/dashboard/mapper/OnlineMapper.java
  81. 16 0
      src/main/java/com/zhili/dashboard/mapper/OrgMapper.java
  82. 16 0
      src/main/java/com/zhili/dashboard/mapper/StatisticsMapper.java
  83. 288 0
      src/main/java/com/zhili/dashboard/redis/RedisCache.java
  84. 23 0
      src/main/java/com/zhili/dashboard/req/MapParam.java
  85. 20 0
      src/main/java/com/zhili/dashboard/req/ProvinceParam.java
  86. 23 0
      src/main/java/com/zhili/dashboard/req/RadarParam.java
  87. 42 0
      src/main/java/com/zhili/dashboard/req/TableInfoParam.java
  88. 75 0
      src/main/java/com/zhili/dashboard/scheduler/JobScheduler.java
  89. 172 0
      src/main/java/com/zhili/dashboard/service/IAlarmMsgService.java
  90. 19 0
      src/main/java/com/zhili/dashboard/service/IAlarmMsgWarnService.java
  91. 16 0
      src/main/java/com/zhili/dashboard/service/ICommandService.java
  92. 19 0
      src/main/java/com/zhili/dashboard/service/IDeviceDurationService.java
  93. 20 0
      src/main/java/com/zhili/dashboard/service/IDeviceService.java
  94. 16 0
      src/main/java/com/zhili/dashboard/service/IOrgService.java
  95. 16 0
      src/main/java/com/zhili/dashboard/service/IStatisticsService.java
  96. 244 0
      src/main/java/com/zhili/dashboard/service/TokenService.java
  97. 1559 0
      src/main/java/com/zhili/dashboard/service/impl/AlarmMsgServiceImpl.java
  98. 322 0
      src/main/java/com/zhili/dashboard/service/impl/AlarmMsgWarnServiceImpl.java
  99. 20 0
      src/main/java/com/zhili/dashboard/service/impl/CommandServiceImpl.java
  100. 142 0
      src/main/java/com/zhili/dashboard/service/impl/DeviceDurationServiceImpl.java

+ 44 - 0
.drone.yml

@@ -0,0 +1,44 @@
+kind: pipeline
+name: default
+
+steps:
+  - name: restore-cache
+    image: drillster/drone-volume-cache
+    volumes:
+      - name: cache
+        path: /cache
+    settings:
+      restore: true
+      mount:
+        - .m2
+
+  - name: build
+    image: jaikuai/npm-mvn
+    pull: true
+    commands:
+      - mvn clean install -Dmaven.test.skip=true -Dmaven.repo.local=/drone/src/.m2/repository -Dmaven.compile.fork=true package
+
+  - name: rebuild-cache
+    image: drillster/drone-volume-cache
+    volumes:
+      - name: cache
+        path: /cache
+    settings:
+      rebuild: true
+      mount:
+        - .m2
+
+  - name: docker-hz-admin-server
+    image: plugins/docker
+    settings:
+      tags:
+        - latest
+        - 1.0.${DRONE_BUILD_NUMBER}
+      registry: nas.fast-fun.cn:5000
+      insecure: true
+      repo: nas.fast-fun.cn:5000/screen/omes-api
+
+volumes:
+  - name: cache
+    host:
+      path: /home/drone/cache

+ 33 - 0
.gitignore

@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/

BIN
.mvn/wrapper/maven-wrapper.jar


+ 2 - 0
.mvn/wrapper/maven-wrapper.properties

@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar

+ 5 - 0
Dockerfile

@@ -0,0 +1,5 @@
+FROM nas.fast-fun.cn:5000/java:8-jre-alpine
+
+ENV PRO_NAME=dashboard PRO_ENV=dev TZ="Asia/Shanghai"
+
+COPY ./target/dashboard-1.0.1.jar /home/App.jar

+ 331 - 0
mvnw

@@ -0,0 +1,331 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+#   JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+#   M2_HOME - location of maven2's installed home dir
+#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
+#     e.g. to debug Maven itself, use
+#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ]; then
+
+  if [ -f /usr/local/etc/mavenrc ]; then
+    . /usr/local/etc/mavenrc
+  fi
+
+  if [ -f /etc/mavenrc ]; then
+    . /etc/mavenrc
+  fi
+
+  if [ -f "$HOME/.mavenrc" ]; then
+    . "$HOME/.mavenrc"
+  fi
+
+fi
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false
+darwin=false
+mingw=false
+case "$(uname)" in
+CYGWIN*) cygwin=true ;;
+MINGW*) mingw=true ;;
+Darwin*)
+  darwin=true
+  # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+  # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+  if [ -z "$JAVA_HOME" ]; then
+    if [ -x "/usr/libexec/java_home" ]; then
+      export JAVA_HOME="$(/usr/libexec/java_home)"
+    else
+      export JAVA_HOME="/Library/Java/Home"
+    fi
+  fi
+  ;;
+esac
+
+if [ -z "$JAVA_HOME" ]; then
+  if [ -r /etc/gentoo-release ]; then
+    JAVA_HOME=$(java-config --jre-home)
+  fi
+fi
+
+if [ -z "$M2_HOME" ]; then
+  ## resolve links - $0 may be a link to maven's home
+  PRG="$0"
+
+  # need this for relative symlinks
+  while [ -h "$PRG" ]; do
+    ls=$(ls -ld "$PRG")
+    link=$(expr "$ls" : '.*-> \(.*\)$')
+    if expr "$link" : '/.*' >/dev/null; then
+      PRG="$link"
+    else
+      PRG="$(dirname "$PRG")/$link"
+    fi
+  done
+
+  saveddir=$(pwd)
+
+  M2_HOME=$(dirname "$PRG")/..
+
+  # make it fully qualified
+  M2_HOME=$(cd "$M2_HOME" && pwd)
+
+  cd "$saveddir"
+  # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=$(cygpath --unix "$M2_HOME")
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME="$( (
+      cd "$M2_HOME"
+      pwd
+    ))"
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME="$( (
+      cd "$JAVA_HOME"
+      pwd
+    ))"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+  javaExecutable="$(which javac)"
+  if [ -n "$javaExecutable" ] && ! [ "$(expr \"$javaExecutable\" : '\([^ ]*\)')" = "no" ]; then
+    # readlink(1) is not available as standard on Solaris 10.
+    readLink=$(which readlink)
+    if [ ! $(expr "$readLink" : '\([^ ]*\)') = "no" ]; then
+      if $darwin; then
+        javaHome="$(dirname \"$javaExecutable\")"
+        javaExecutable="$(cd \"$javaHome\" && pwd -P)/javac"
+      else
+        javaExecutable="$(readlink -f \"$javaExecutable\")"
+      fi
+      javaHome="$(dirname \"$javaExecutable\")"
+      javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+      JAVA_HOME="$javaHome"
+      export JAVA_HOME
+    fi
+  fi
+fi
+
+if [ -z "$JAVACMD" ]; then
+  if [ -n "$JAVA_HOME" ]; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ]; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+    fi
+  else
+    JAVACMD="$(
+      \unset -f command
+      \command -v java
+    )"
+  fi
+fi
+
+if [ ! -x "$JAVACMD" ]; then
+  echo "Error: JAVA_HOME is not defined correctly." >&2
+  echo "  We cannot execute $JAVACMD" >&2
+  exit 1
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+  echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+  if [ -z "$1" ]; then
+    echo "Path not specified to find_maven_basedir"
+    return 1
+  fi
+
+  basedir="$1"
+  wdir="$1"
+  while [ "$wdir" != '/' ]; do
+    if [ -d "$wdir"/.mvn ]; then
+      basedir=$wdir
+      break
+    fi
+    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+    if [ -d "${wdir}" ]; then
+      wdir=$(
+        cd "$wdir/.."
+        pwd
+      )
+    fi
+    # end of workaround
+  done
+  echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+  if [ -f "$1" ]; then
+    echo "$(tr -s '\n' ' ' <"$1")"
+  fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(pwd)")
+if [ -z "$BASE_DIR" ]; then
+  exit 1
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+  if [ "$MVNW_VERBOSE" = true ]; then
+    echo "Found .mvn/wrapper/maven-wrapper.jar"
+  fi
+else
+  if [ "$MVNW_VERBOSE" = true ]; then
+    echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+  fi
+  if [ -n "$MVNW_REPOURL" ]; then
+    jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+  else
+    jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+  fi
+  while IFS="=" read key value; do
+    case "$key" in wrapperUrl)
+      jarUrl="$value"
+      break
+      ;;
+    esac
+  done <"$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+  if [ "$MVNW_VERBOSE" = true ]; then
+    echo "Downloading from: $jarUrl"
+  fi
+  wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+  if $cygwin; then
+    wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+  fi
+
+  if command -v wget >/dev/null; then
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Found wget ... using wget"
+    fi
+    if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+      wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+    else
+      wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+    fi
+  elif command -v curl >/dev/null; then
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Found curl ... using curl"
+    fi
+    if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+      curl -o "$wrapperJarPath" "$jarUrl" -f
+    else
+      curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+    fi
+
+  else
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Falling back to using Java to download"
+    fi
+    javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+    # For Cygwin, switch paths to Windows format before running javac
+    if $cygwin; then
+      javaClass=$(cygpath --path --windows "$javaClass")
+    fi
+    if [ -e "$javaClass" ]; then
+      if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo " - Compiling MavenWrapperDownloader.java ..."
+        fi
+        # Compiling the Java class
+        ("$JAVA_HOME/bin/javac" "$javaClass")
+      fi
+      if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+        # Running the downloader
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo " - Running MavenWrapperDownloader.java ..."
+        fi
+        ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+      fi
+    fi
+  fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+  echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=$(cygpath --path --windows "$M2_HOME")
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+    MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+  $MAVEN_OPTS \
+  $MAVEN_DEBUG_OPTS \
+  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+  "-Dmaven.home=${M2_HOME}" \
+  "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

+ 188 - 0
mvnw.cmd

@@ -0,0 +1,188 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements.  See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership.  The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License.  You may obtain a copy of the License at
+@REM
+@REM    https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied.  See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM     e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+    IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Found %WRAPPER_JAR%
+    )
+) else (
+    if not "%MVNW_REPOURL%" == "" (
+        SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+    )
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Couldn't find %WRAPPER_JAR%, downloading it ...
+        echo Downloading from: %DOWNLOAD_URL%
+    )
+
+    powershell -Command "&{"^
+		"$webclient = new-object System.Net.WebClient;"^
+		"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+		"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+		"}"^
+		"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+		"}"
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Finished downloading %WRAPPER_JAR%
+    )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+  %JVM_CONFIG_MAVEN_PROPS% ^
+  %MAVEN_OPTS% ^
+  %MAVEN_DEBUG_OPTS% ^
+  -classpath %WRAPPER_JAR% ^
+  "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+  %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%

+ 160 - 0
pom.xml

@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.7.1</version>
+        <relativePath/>
+    </parent>
+    <groupId>com.dashboard</groupId>
+    <artifactId>dashboard</artifactId>
+    <version>1.0.1</version>
+    <packaging>jar</packaging>
+    <name>omes-dashboard</name>
+    <description>omes-dashboard</description>
+    <properties>
+        <java.version>1.8</java.version>
+        <fastjson.version>1.2.83</fastjson.version>
+        <mybatis.version>3.5.2</mybatis.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+        <junit.version>4.13</junit.version>
+        <pagehelper.boot.version>1.4.2</pagehelper.boot.version>
+        <bitwalker.version>1.21</bitwalker.version>
+        <okhttp.version>4.9.0</okhttp.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-boot-starter</artifactId>
+            <version>3.0.0</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>io.swagger</groupId>
+                    <artifactId>swagger-models</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <!-- 防止进入swagger页面报类型转换错误,排除3.0.0中的引用,手动增加1.6.2版本 -->
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-models</artifactId>
+            <version>1.6.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <!-- spring security 安全认证-->
+<!--        <dependency>-->
+<!--            <groupId>org.springframework.boot</groupId>-->
+<!--            <artifactId>spring-boot-starter-security</artifactId>-->
+<!--        </dependency>-->
+        <!-- 阿里JSON解析器 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>${fastjson.version}</version>
+        </dependency>
+        <!-- 解析客户端操作系统、浏览器等 -->
+        <dependency>
+            <groupId>eu.bitwalker</groupId>
+            <artifactId>UserAgentUtils</artifactId>
+            <version>${bitwalker.version}</version>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>${mybatis.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-generator</artifactId>
+            <version>3.4.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.freemarker</groupId>
+            <artifactId>freemarker</artifactId>
+            <version>2.3.31</version>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>0.9.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+
+        <!-- redis 缓存操作 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>${junit.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjweaver</artifactId>
+            <version>1.9.9.1</version>
+            <scope>runtime</scope>
+        </dependency>
+        <!-- pagehelper 分页插件 -->
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+            <version>${pagehelper.boot.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>okhttp</artifactId>
+            <version>${okhttp.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>logging-interceptor</artifactId>
+            <version>${okhttp.version}</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 68 - 0
screen.yml

@@ -0,0 +1,68 @@
+version: "3.7"
+services:
+  mysql:
+    hostname: mysql
+    image: mysql:5
+    networks:
+      - screen
+    environment:
+      - MYSQL_ROOT_PASSWORD=Qx123456
+    ports:
+      - 3306:3306
+  redis:
+    hostname: redis
+    image: rpi.it5000.com:5000/redis
+    networks:
+      - screen
+  api-server:
+    hostname: api-server
+    image: nas.fast-fun.cn:5000/screen/omes-api:1.0.5
+    ports:
+      - 9092:8088
+    environment:
+      - PRO_ENV=prod
+    networks:
+      - screen
+    depends_on:
+      - redis
+      - mysql
+  omes-screen:
+    image: nas.fast-fun.cn:5000/screen/omes-screen:1.0.4
+    ports:
+      - 9091:80
+    networks:
+      - screen
+    depends_on:
+      - api-server
+  robot-api:
+    hostname: robot-api
+    image: nas.fast-fun.cn:5000/screen/robot-api:1.0.1
+    environment:
+      - PRO_ENV=prod
+    networks:
+      - screen
+    ports:
+      - 9093:8080
+    depends_on:
+      - redis
+  video:
+    image: nas.fast-fun.cn:5000/screen/zk-screen-video:1.0.4
+    networks:
+      - screen
+    ports:
+      - 9094:8081
+      - 9095:8082
+  robotcv:
+    image: nas.fast-fun.cn:5000/screen/robotcv:1.0.1
+    networks:
+      - screen
+  web:
+    image: nas.fast-fun.cn:5000/screen/zk-screen-web:1.0.4
+    networks:
+      - screen
+    ports:
+      - 9096:8080
+    depends_on:
+      - robot-api
+networks:
+    screen:

+ 27 - 0
src/main/java/com/zhili/dashboard/OmesDashboardApplication.java

@@ -0,0 +1,27 @@
+package com.zhili.dashboard;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**
+ * @author user
+ */
+@SpringBootApplication
+@MapperScan(basePackages = "com.**.mapper")
+@EnableAsync
+@EnableCaching
+@EnableTransactionManagement
+@EnableScheduling
+public class OmesDashboardApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(OmesDashboardApplication.class, args);
+    }
+
+}

+ 16 - 0
src/main/java/com/zhili/dashboard/annotation/RepeatSubmit.java

@@ -0,0 +1,16 @@
+package com.zhili.dashboard.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 自定义注解防止表单重复提交
+ *
+ * @author user
+ */
+@Inherited
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RepeatSubmit {
+
+}

+ 149 - 0
src/main/java/com/zhili/dashboard/base/AjaxResult.java

@@ -0,0 +1,149 @@
+package com.zhili.dashboard.base;
+
+import com.zhili.dashboard.utils.HttpStatus;
+import com.zhili.dashboard.utils.StringUtils;
+
+import java.util.HashMap;
+
+/**
+ * 操作消息提醒
+ * 
+ * @author user
+ */
+public class AjaxResult extends HashMap<String, Object>
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 状态码 */
+    public static final String CODE_TAG = "code";
+
+    /** 返回内容 */
+    public static final String MSG_TAG = "msg";
+
+    /** 数据对象 */
+    public static final String DATA_TAG = "data";
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
+     */
+    public AjaxResult()
+    {
+    }
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象
+     * 
+     * @param code 状态码
+     * @param msg 返回内容
+     */
+    public AjaxResult(int code, String msg)
+    {
+        super.put(CODE_TAG, code);
+        super.put(MSG_TAG, msg);
+    }
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象
+     * 
+     * @param code 状态码
+     * @param msg 返回内容
+     * @param data 数据对象
+     */
+    public AjaxResult(int code, String msg, Object data)
+    {
+        super.put(CODE_TAG, code);
+        super.put(MSG_TAG, msg);
+        if (StringUtils.isNotNull(data))
+        {
+            super.put(DATA_TAG, data);
+        }
+    }
+
+    /**
+     * 返回成功消息
+     * 
+     * @return 成功消息
+     */
+    public static AjaxResult success()
+    {
+        return AjaxResult.success("操作成功");
+    }
+
+    /**
+     * 返回成功数据
+     * 
+     * @return 成功消息
+     */
+    public static AjaxResult success(Object data)
+    {
+        return AjaxResult.success("操作成功", data);
+    }
+
+    /**
+     * 返回成功消息
+     * 
+     * @param msg 返回内容
+     * @return 成功消息
+     */
+    public static AjaxResult success(String msg)
+    {
+        return AjaxResult.success(msg, null);
+    }
+
+    /**
+     * 返回成功消息
+     * 
+     * @param msg 返回内容
+     * @param data 数据对象
+     * @return 成功消息
+     */
+    public static AjaxResult success(String msg, Object data)
+    {
+        return new AjaxResult(HttpStatus.SUCCESS, msg, data);
+    }
+
+    /**
+     * 返回错误消息
+     * 
+     * @return
+     */
+    public static AjaxResult error()
+    {
+        return AjaxResult.error("操作失败");
+    }
+
+    /**
+     * 返回错误消息
+     * 
+     * @param msg 返回内容
+     * @return 警告消息
+     */
+    public static AjaxResult error(String msg)
+    {
+        return AjaxResult.error(msg, null);
+    }
+
+    /**
+     * 返回错误消息
+     * 
+     * @param msg 返回内容
+     * @param data 数据对象
+     * @return 警告消息
+     */
+    public static AjaxResult error(String msg, Object data)
+    {
+        return new AjaxResult(HttpStatus.ERROR, msg, data);
+    }
+
+    /**
+     * 返回错误消息
+     * 
+     * @param code 状态码
+     * @param msg 返回内容
+     * @return 警告消息
+     */
+    public static AjaxResult error(int code, String msg)
+    {
+        return new AjaxResult(code, msg, null);
+    }
+}

+ 29 - 0
src/main/java/com/zhili/dashboard/base/BaseCycleChartVo.java

@@ -0,0 +1,29 @@
+package com.zhili.dashboard.base;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @author zyg
+ * @className BaseCycleChartVo 环状图基础数据类
+ * @date 2022年01月12日 9:37
+ */
+@Data
+public class BaseCycleChartVo implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("名称")
+    private String name;
+
+    @ApiModelProperty("等级图标")
+    private String levelIcon;
+
+    @ApiModelProperty("数量")
+    private Long count;
+
+    @ApiModelProperty("百分比,保留两位小数")
+    private BigDecimal percent = BigDecimal.ZERO;
+}

+ 78 - 0
src/main/java/com/zhili/dashboard/base/BaseEntity.java

@@ -0,0 +1,78 @@
+package com.zhili.dashboard.base;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.data.annotation.Id;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * @author zyg
+ * @date 2021年11月18日 15:17
+ */
+@Data
+@ApiModel(value = "BaseEntity", description = "实体基类")
+public class BaseEntity implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键自增
+     */
+    @Id
+    @TableId(type = IdType.AUTO)
+    @ApiModelProperty(value = "主键id")
+    protected Long id;
+
+    /**
+     * 创建时间(新增时自动填充创建时间)
+     */
+    @ApiModelProperty(value = "创建时间")
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
+    @JsonSerialize(using = LocalDateTimeSerializer.class)
+    protected LocalDateTime createTime;
+
+    /**
+     * 更新时间(新增/更新时自动填充更新时间)
+     */
+    @ApiModelProperty(value = "更新时间")
+    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
+    @JsonSerialize(using = LocalDateTimeSerializer.class)
+    protected LocalDateTime updateTime;
+
+    /**
+     * 创建者(新增自动填充)
+     */
+    @ApiModelProperty(value = "创建者")
+    @TableField(fill = FieldFill.INSERT)
+    protected String createBy;
+
+    /**
+     * 更新人(新增/更新时自动填充)
+     */
+    @ApiModelProperty(value = "更新人")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    protected String updateBy;
+
+    /**
+     * 是否已删除 0:未删除 1:已删除
+     */
+    @ApiModelProperty(value = "是否已删除 0:未删除 1:已删除")
+    private Integer isDelete = 0;
+
+}

+ 23 - 0
src/main/java/com/zhili/dashboard/base/BaseIntegerLineChartVo.java

@@ -0,0 +1,23 @@
+package com.zhili.dashboard.base;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author zyg
+ * @className BaseLineChartVo
+ * @date 2022年01月12日 9:37
+ */
+@Data
+public class BaseIntegerLineChartVo implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "横轴")
+    private List<String> xAxis;
+
+    @ApiModelProperty(value = "各类数值")
+    private List<KindValueListVo> kindList;
+}

+ 24 - 0
src/main/java/com/zhili/dashboard/base/BaseLineChartVo.java

@@ -0,0 +1,24 @@
+package com.zhili.dashboard.base;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author zyg
+ * @className BaseLineChartVo
+ * @date 2022年01月12日 9:37
+ */
+@Data
+public class BaseLineChartVo implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "时间轴")
+    private List<String> timeAxis;
+
+    @ApiModelProperty(value = "各类数值")
+    private List<KindValueListVo> kindList;
+}

+ 23 - 0
src/main/java/com/zhili/dashboard/base/BaseLineDecimalVo.java

@@ -0,0 +1,23 @@
+package com.zhili.dashboard.base;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author zyg
+ * @className BaseLineChartVo
+ * @date 2022年01月12日 9:37
+ */
+@Data
+public class BaseLineDecimalVo implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "时间轴")
+    private List<String> timeAxis;
+
+    @ApiModelProperty(value = "各类数值")
+    private List<KindValueDoubleListVo> kindList;
+}

+ 213 - 0
src/main/java/com/zhili/dashboard/base/Constants.java

@@ -0,0 +1,213 @@
+package com.zhili.dashboard.base;
+
+import io.jsonwebtoken.Claims;
+
+/**
+ * 通用常量信息
+ *
+ * @author user
+ */
+public class Constants {
+    /**
+     * 热管理--温差图表名称
+     */
+    public static final String HZ_SUCCESS_RESPONSE_CODE = "20000";
+    /**
+     * 热管理--温差图表名称
+     */
+    public static final String HOT_CHART_NAME = "温差";
+    /**
+     * 单体电压
+     */
+    public static final String CELL_VOLTAGE = "单体电压";
+    /**
+     * 单体温度
+     */
+    public static final String CELL_TEMPERATURE = "单体温度";
+    /**
+     * 验证码有效期(分钟)
+     */
+    public static final Integer SUCCESS_RESPONSE_CODE = 200;
+    /**
+     * createBy
+     */
+    public static final Float BATTERY_ERROR_CODE = -9999f;
+    /**
+     * createBy
+     */
+    public static final String CREATE_BY = "createBy";
+    /**
+     * createTime
+     */
+    public static final String CREATE_TIME = "createTime";
+    /**
+     * updateBy
+     */
+    public static final String UPDATE_BY = "updateBy";
+    /**
+     * updateTime
+     */
+    public static final String UPDATE_TIME = "updateTime";
+    /**
+     * UTF-8 字符集
+     */
+    public static final String OK = "OK";
+    /**
+     * UTF-8 字符集
+     */
+    public static final String FAILED = "操作失败";
+    /**
+     * DESC
+     */
+    public static final String DESC = "DESC";
+    /**
+     * ASC
+     */
+    public static final String ASC = "ASC";
+    /**
+     * DBC
+     */
+    public static final String DBC = "DBC";
+    /**
+     * UTF-8 字符集
+     */
+    public static final String UTF8 = "UTF-8";
+
+    /**
+     * GBK 字符集
+     */
+    public static final String GBK = "GBK";
+
+    /**
+     * http请求
+     */
+    public static final String HTTP = "http://";
+
+    /**
+     * https请求
+     */
+    public static final String HTTPS = "https://";
+
+    /**
+     * 通用成功标识
+     */
+    public static final String SUCCESS = "0";
+
+    /**
+     * 通用失败标识
+     */
+    public static final String FAIL = "1";
+
+    /**
+     * 登录成功
+     */
+    public static final String LOGIN_SUCCESS = "Success";
+
+    /**
+     * 注销
+     */
+    public static final String LOGOUT = "Logout";
+
+    /**
+     * 注册
+     */
+    public static final String REGISTER = "Register";
+
+    /**
+     * 登录失败
+     */
+    public static final String LOGIN_FAIL = "Error";
+
+    /**
+     * 验证码 redis key
+     */
+    public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
+
+    /**
+     * 登录用户 redis key
+     */
+    public static final String LOGIN_TOKEN_KEY = "login_tokens:";
+
+    /**
+     * 防重提交 redis key
+     */
+    public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
+
+    /**
+     * 限流 redis key
+     */
+    public static final String RATE_LIMIT_KEY = "rate_limit:";
+
+    /**
+     * 验证码有效期(分钟)
+     */
+    public static final Integer CAPTCHA_EXPIRATION = 2;
+
+    /**
+     * 令牌
+     */
+    public static final String TOKEN = "token";
+    /**
+     * 企业微信令牌
+     */
+    public static final String ACCESS_TOKEN = "access_token";
+    /**
+     * 令牌前缀
+     */
+    public static final String TOKEN_PREFIX = "Bearer ";
+
+    /**
+     * 令牌前缀
+     */
+    public static final String LOGIN_USER_KEY = "login_user_key";
+
+    /**
+     * 用户ID
+     */
+    public static final String JWT_USERID = "userid";
+
+    /**
+     * 用户名称
+     */
+    public static final String JWT_USERNAME = Claims.SUBJECT;
+
+    /**
+     * 用户头像
+     */
+    public static final String JWT_AVATAR = "avatar";
+
+    /**
+     * 创建时间
+     */
+    public static final String JWT_CREATED = "created";
+
+    /**
+     * 用户权限
+     */
+    public static final String JWT_AUTHORITIES = "authorities";
+
+    /**
+     * 参数管理 cache key
+     */
+    public static final String SYS_CONFIG_KEY = "sys_config:";
+
+    /**
+     * 字典管理 cache key
+     */
+    public static final String SYS_DICT_KEY = "sys_dict:";
+
+    /**
+     * 字典管理 cache key
+     */
+    public static final String MODEL_KEY = "algo_param_from_mysql:";
+
+    /**
+     * 资源映射路径 前缀
+     */
+    public static final String RESOURCE_PREFIX = "/profile";
+
+    /**
+     * RMI 远程方法调用
+     */
+    public static final String LOOKUP_RMI = "rmi://";
+}

+ 16 - 0
src/main/java/com/zhili/dashboard/base/HzTokenResponse.java

@@ -0,0 +1,16 @@
+package com.zhili.dashboard.base;
+
+import lombok.Data;
+
+/**
+ * @author zyg
+ * @className QyResponse
+ * @date 2022年02月14日 16:09
+ */
+@Data
+public class HzTokenResponse {
+    private Integer code;
+    private String data;
+    private String description;
+    private String msg;
+}

+ 28 - 0
src/main/java/com/zhili/dashboard/base/IdParam.java

@@ -0,0 +1,28 @@
+package com.zhili.dashboard.base;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * @author zyg
+ * @className IdParam
+ * @date 2021年11月24日 12:25
+ */
+public class IdParam {
+    private static final long serialVersionUID = 1L;
+    @ApiModelProperty(
+            value = "参数ID,多个用','分隔",
+            name = "id"
+    )
+    private String id;
+
+    public IdParam() {
+    }
+
+    public void setId(final String id) {
+        this.id = id;
+    }
+
+    public String getId() {
+        return this.id;
+    }
+}

+ 22 - 0
src/main/java/com/zhili/dashboard/base/KindValueDoubleListVo.java

@@ -0,0 +1,22 @@
+package com.zhili.dashboard.base;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * @author zyg
+ * @className PageParam
+ * @date 2021年11月24日 16:08
+ */
+@Data
+public class KindValueDoubleListVo {
+
+    @ApiModelProperty(value = "类别名称")
+    private String name;
+
+    @ApiModelProperty(value = "数值")
+    private List<BigDecimal> value;
+}

+ 21 - 0
src/main/java/com/zhili/dashboard/base/KindValueListVo.java

@@ -0,0 +1,21 @@
+package com.zhili.dashboard.base;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author zyg
+ * @className PageParam
+ * @date 2021年11月24日 16:08
+ */
+@Data
+public class KindValueListVo {
+
+    @ApiModelProperty(value = "类别名称")
+    private String name;
+
+    @ApiModelProperty(value = "数值")
+    private List<Long> value;
+}

+ 73 - 0
src/main/java/com/zhili/dashboard/base/LoginBody.java

@@ -0,0 +1,73 @@
+package com.zhili.dashboard.base;
+
+/**
+ * 用户登录对象
+ *
+ * @author user
+ */
+public class LoginBody {
+    /**
+     * 用户名
+     */
+    private String username;
+
+    /**
+     * 用户密码
+     */
+    private String password;
+
+    /**
+     * 验证码
+     */
+    private String code;
+
+    /**
+     * 刷新token
+     */
+    private String refreshToken;
+
+    public String getRefreshToken() {
+        return refreshToken;
+    }
+
+    public void setRefreshToken(String refreshToken) {
+        this.refreshToken = refreshToken;
+    }
+
+    /**
+     * 唯一标识
+     */
+    private String uuid = "";
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getUuid() {
+        return uuid;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+}

+ 264 - 0
src/main/java/com/zhili/dashboard/base/LoginUser.java

@@ -0,0 +1,264 @@
+//package com.base;
+//
+//import com.UserInfo.entity.UserInfo;
+//import com.fasterxml.jackson.annotation.JsonIgnore;
+//import org.springframework.security.core.GrantedAuthority;
+//import org.springframework.security.core.userdetails.UserDetails;
+//
+//import java.util.Collection;
+//import java.util.Set;
+//
+///**
+// * 登录用户身份权限
+// *
+// * @author user
+// */
+//public class LoginUser implements UserDetails
+//{
+//    private static final long serialVersionUID = 1L;
+//
+//    /**
+//     * 用户ID
+//     */
+//    private Long id;
+//
+//    /**
+//     * 部门ID
+//     */
+//    private Long deptId;
+//
+//    /**
+//     * 用户唯一标识
+//     */
+//    private String token;
+//
+//    /**
+//     * 登录时间
+//     */
+//    private Long loginTime;
+//
+//    /**
+//     * 过期时间
+//     */
+//    private Long expireTime;
+//
+//    /**
+//     * 登录IP地址
+//     */
+//    private String ipaddr;
+//
+//    /**
+//     * 登录地点
+//     */
+//    private String loginLocation;
+//
+//    /**
+//     * 浏览器类型
+//     */
+//    private String browser;
+//
+//    /**
+//     * 操作系统
+//     */
+//    private String os;
+//
+//    /**
+//     * 权限列表
+//     */
+//    private Set<String> permissions;
+//
+//    /**
+//     * 用户信息
+//     */
+//    private UserInfo user;
+//
+//    public Long getId()
+//    {
+//        return id;
+//    }
+//
+//    public void setId(Long id)
+//    {
+//        this.id = id;
+//    }
+//
+//    public Long getDeptId()
+//    {
+//        return deptId;
+//    }
+//
+//    public void setDeptId(Long deptId)
+//    {
+//        this.deptId = deptId;
+//    }
+//
+//    public String getToken()
+//    {
+//        return token;
+//    }
+//
+//    public void setToken(String token)
+//    {
+//        this.token = token;
+//    }
+//
+//    public LoginUser()
+//    {
+//    }
+//
+//    public LoginUser(UserInfo user, Set<String> permissions)
+//    {
+//        this.user = user;
+//    }
+//
+//    public LoginUser(Long userId, Long deptId, UserInfo user, Set<String> permissions)
+//    {
+//        this.id = userId;
+//        this.user = user;
+//    }
+//
+//    @JsonIgnore
+//    @Override
+//    public String getPassword()
+//    {
+//        return user.getPwd();
+//    }
+//
+//    @Override
+//    public String getUsername()
+//    {
+//        return user.getUserName();
+//    }
+//
+//    /**
+//     * 账户是否未过期,过期无法验证
+//     */
+//    @JsonIgnore
+//    @Override
+//    public boolean isAccountNonExpired()
+//    {
+//        return true;
+//    }
+//
+//    /**
+//     * 指定用户是否解锁,锁定的用户无法进行身份验证
+//     *
+//     * @return
+//     */
+//    @JsonIgnore
+//    @Override
+//    public boolean isAccountNonLocked()
+//    {
+//        return true;
+//    }
+//
+//    /**
+//     * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
+//     *
+//     * @return
+//     */
+//    @JsonIgnore
+//    @Override
+//    public boolean isCredentialsNonExpired()
+//    {
+//        return true;
+//    }
+//
+//    /**
+//     * 是否可用 ,禁用的用户不能身份验证
+//     *
+//     * @return
+//     */
+//    @JsonIgnore
+//    @Override
+//    public boolean isEnabled()
+//    {
+//        return true;
+//    }
+//
+//    public Long getLoginTime()
+//    {
+//        return loginTime;
+//    }
+//
+//    public void setLoginTime(Long loginTime)
+//    {
+//        this.loginTime = loginTime;
+//    }
+//
+//    public String getIpaddr()
+//    {
+//        return ipaddr;
+//    }
+//
+//    public void setIpaddr(String ipaddr)
+//    {
+//        this.ipaddr = ipaddr;
+//    }
+//
+//    public String getLoginLocation()
+//    {
+//        return loginLocation;
+//    }
+//
+//    public void setLoginLocation(String loginLocation)
+//    {
+//        this.loginLocation = loginLocation;
+//    }
+//
+//    public String getBrowser()
+//    {
+//        return browser;
+//    }
+//
+//    public void setBrowser(String browser)
+//    {
+//        this.browser = browser;
+//    }
+//
+//    public String getOs()
+//    {
+//        return os;
+//    }
+//
+//    public void setOs(String os)
+//    {
+//        this.os = os;
+//    }
+//
+//    public Long getExpireTime()
+//    {
+//        return expireTime;
+//    }
+//
+//    public void setExpireTime(Long expireTime)
+//    {
+//        this.expireTime = expireTime;
+//    }
+//
+//    public Set<String> getPermissions()
+//    {
+//        return permissions;
+//    }
+//
+//    public void setPermissions(Set<String> permissions)
+//    {
+//        this.permissions = permissions;
+//    }
+//
+//    public UserInfo getUser()
+//    {
+//        return user;
+//    }
+//
+//    public void setUser(UserInfo user)
+//    {
+//        this.user = user;
+//    }
+//
+//    @Override
+//    public Collection<? extends GrantedAuthority> getAuthorities()
+//    {
+//        return null;
+//    }
+//}

+ 27 - 0
src/main/java/com/zhili/dashboard/base/PageParam.java

@@ -0,0 +1,27 @@
+package com.zhili.dashboard.base;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @author zyg
+ * @className PageParam
+ * @date 2021年11月24日 16:08
+ */
+@Data
+public class PageParam {
+    @ApiModelProperty(value = "分页数量", name = "pageSize")
+    private Integer pageSize;
+    @ApiModelProperty(value = "分页索引", name = "pageIndex")
+    private Integer pageIndex;
+    @ApiModelProperty(value = "开始时间")
+    @JsonFormat(pattern = "yyyy-MM-dd 00:00:00", timezone = "GMT+8")
+    private String startTime;
+    @ApiModelProperty(value = "截止时间")
+    @JsonFormat(pattern = "yyyy-MM-dd 23:59:59", timezone = "GMT+8")
+    private String endTime;
+    @ApiModelProperty(value = "组织机构id")
+    private String orgId;
+
+}

+ 88 - 0
src/main/java/com/zhili/dashboard/base/UserInfoVO.java

@@ -0,0 +1,88 @@
+package com.zhili.dashboard.base;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+
+/**
+ * <p>
+ * 用户信息表 返回VO对象
+ * </p>
+ *
+ * @author MiaoXiaoTao
+ * @since 2021-01-07
+ */
+@Data
+public class UserInfoVO {
+
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**用户名*/
+    private String userName;
+
+/**手机号(账号)*/
+    private String mobile;
+
+    // /**密码*/
+    //  private String pwd;
+
+ /**组织机构id*/
+    private String orgId;
+
+    /**roleId*/
+    private Integer roleId;
+
+
+    /**状态:0:禁用、1启用、*/
+    private Integer status;
+
+    /**0:正常,1:删除*/
+    private Integer del;
+
+    /**1:永久,2:临时*/
+    private Integer accountType;
+
+    /**最后一次登录时间*/
+    private String lastLoginTime;
+
+    /**开始有效*/
+    private String accountBeginValidDate;
+
+    /**结束有效*/
+    private String accountEndValidDate;
+
+    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
+    @JsonSerialize(using = LocalDateTimeSerializer.class)
+    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+    private LocalDateTime createTime;
+    private String createBy;
+
+    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
+    @JsonSerialize(using = LocalDateTimeSerializer.class)
+    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+    private LocalDateTime updateTime;
+
+    private String updateBy;
+
+    /**角色名称*/
+    private String roleText;
+
+    /**组织机构名称*/
+    private String orgText;
+    /**是否管理员 0:否,1:是*/
+    private Integer isAdmin;
+
+    /**页面权限*/
+    private List<String> permissions;
+}

+ 22 - 0
src/main/java/com/zhili/dashboard/base/UserInformationDTO.java

@@ -0,0 +1,22 @@
+package com.zhili.dashboard.base;
+
+import lombok.Builder;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author zyg
+ * @className UserInformationDTO
+ * @date 2021年12月22日 12:58
+ */
+@Builder
+@Data
+public class UserInformationDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private Integer userId;
+    private String account;
+    private String name;
+    private Long cloudId;
+}

+ 72 - 0
src/main/java/com/zhili/dashboard/config/FastJson2JsonRedisSerializer.java

@@ -0,0 +1,72 @@
+package com.zhili.dashboard.config;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.parser.ParserConfig;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.SerializationException;
+import org.springframework.util.Assert;
+
+import java.nio.charset.Charset;
+
+/**
+ * Redis使用FastJson序列化
+ * 
+ * @author user
+ */
+public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
+{
+    @SuppressWarnings("unused")
+    private ObjectMapper objectMapper = new ObjectMapper();
+
+    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
+
+    private Class<T> clazz;
+
+    static
+    {
+        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
+    }
+
+    public FastJson2JsonRedisSerializer(Class<T> clazz)
+    {
+        super();
+        this.clazz = clazz;
+    }
+
+    @Override
+    public byte[] serialize(T t) throws SerializationException
+    {
+        if (t == null)
+        {
+            return new byte[0];
+        }
+        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
+    }
+
+    @Override
+    public T deserialize(byte[] bytes) throws SerializationException
+    {
+        if (bytes == null || bytes.length <= 0)
+        {
+            return null;
+        }
+        String str = new String(bytes, DEFAULT_CHARSET);
+
+        return JSON.parseObject(str, clazz);
+    }
+
+    public void setObjectMapper(ObjectMapper objectMapper)
+    {
+        Assert.notNull(objectMapper, "'objectMapper' must not be null");
+        this.objectMapper = objectMapper;
+    }
+
+    protected JavaType getJavaType(Class<?> clazz)
+    {
+        return TypeFactory.defaultInstance().constructType(clazz);
+    }
+}

+ 124 - 0
src/main/java/com/zhili/dashboard/config/HzConfig.java

@@ -0,0 +1,124 @@
+package com.zhili.dashboard.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 读取项目相关配置
+ * 
+ * @author user
+ */
+@Component
+@ConfigurationProperties(prefix = "hz")
+public class HzConfig
+{
+    /** 项目名称 */
+    private String name;
+
+    /** 版本 */
+    private String version;
+
+    /** 版权年份 */
+    private String copyrightYear;
+
+    /** 实例演示开关 */
+    private boolean demoEnabled;
+
+    /** 上传路径 */
+    private static String profile;
+
+    /** 获取地址开关 */
+    private static boolean addressEnabled;
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public String getVersion()
+    {
+        return version;
+    }
+
+    public void setVersion(String version)
+    {
+        this.version = version;
+    }
+
+    public String getCopyrightYear()
+    {
+        return copyrightYear;
+    }
+
+    public void setCopyrightYear(String copyrightYear)
+    {
+        this.copyrightYear = copyrightYear;
+    }
+
+    public boolean isDemoEnabled()
+    {
+        return demoEnabled;
+    }
+
+    public void setDemoEnabled(boolean demoEnabled)
+    {
+        this.demoEnabled = demoEnabled;
+    }
+
+    public static String getProfile()
+    {
+        return profile;
+    }
+
+    public void setProfile(String profile)
+    {
+        HzConfig.profile = profile;
+    }
+
+    public static boolean isAddressEnabled()
+    {
+        return addressEnabled;
+    }
+
+    public void setAddressEnabled(boolean addressEnabled)
+    {
+        HzConfig.addressEnabled = addressEnabled;
+    }
+
+    /**
+     * 获取导入上传路径
+     */
+    public static String getImportPath()
+    {
+        return getProfile() + "/import";
+    }
+
+    /**
+     * 获取头像上传路径
+     */
+    public static String getAvatarPath()
+    {
+        return getProfile() + "/avatar";
+    }
+
+    /**
+     * 获取下载路径
+     */
+    public static String getDownloadPath()
+    {
+        return getProfile() + "/download/";
+    }
+
+    /**
+     * 获取上传路径
+     */
+    public static String getUploadPath()
+    {
+        return getProfile() + "/upload";
+    }
+}

+ 43 - 0
src/main/java/com/zhili/dashboard/config/MybatisPlusConfig.java

@@ -0,0 +1,43 @@
+package com.zhili.dashboard.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.core.config.GlobalConfig;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import com.zhili.dashboard.handler.CustomMetaObjectHandler;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author zyg
+ */
+@Configuration
+public class MybatisPlusConfig {
+    @Bean
+    public GlobalConfig globalConfig() {
+        GlobalConfig globalConfig = new GlobalConfig();
+        globalConfig.setMetaObjectHandler(new CustomMetaObjectHandler());
+        globalConfig.setBanner(false);
+        return globalConfig;
+    }
+
+    /**
+     * 新的分页插件,一缓和二缓遵循mybatis的规则,
+     * 需要设置 MybatisConfiguration#useDeprecatedExecutor = false
+     * 避免缓存出现问题(该属性会在旧插件移除后一同移除)
+     */
+    @Bean
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
+        //分页插件
+        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
+        // 防止全表更新和删除
+        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
+        // 乐观锁插件
+        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
+        return interceptor;
+    }
+}

+ 92 - 0
src/main/java/com/zhili/dashboard/config/OkHttpConfiguration.java

@@ -0,0 +1,92 @@
+package com.zhili.dashboard.config;
+
+import okhttp3.ConnectionPool;
+import okhttp3.OkHttpClient;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author user
+ * @date 2019-04-09
+ */
+@Configuration
+public class OkHttpConfiguration {
+    @Value("${ok.http.connect-timeout}")
+    private Integer connectTimeout;
+    @Value("${ok.http.read-timeout}")
+    private Integer readTimeout;
+    @Value("${ok.http.write-timeout}")
+    private Integer writeTimeout;
+    @Value("${ok.http.max-idle-connections}")
+    private Integer maxIdleConnections;
+    @Value("${ok.http.keep-alive-duration}")
+    private Long keepAliveDuration;
+
+    @Bean
+    public OkHttpClient okHttpClient() {
+        return new OkHttpClient.Builder()
+                .sslSocketFactory(sslSocketFactory(), x509TrustManager())
+                // 是否开启缓存
+                .retryOnConnectionFailure(false)
+                .connectionPool(pool())
+                .connectTimeout(connectTimeout == null ? 60 : connectTimeout, TimeUnit.SECONDS)
+                .readTimeout(readTimeout == null ? 60 : readTimeout, TimeUnit.SECONDS)
+                .writeTimeout(writeTimeout == null ? 60 : writeTimeout, TimeUnit.SECONDS)
+                .hostnameVerifier((hostname, session) -> true)
+                // 设置代理
+//      .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8888)))
+                // 拦截器
+//    .addInterceptor()
+                .build();
+    }
+
+    @Bean
+    public X509TrustManager x509TrustManager() {
+        return new X509TrustManager() {
+            @Override
+            public void checkClientTrusted(X509Certificate[] chain, String authType)
+                    throws CertificateException {
+            }
+
+            @Override
+            public void checkServerTrusted(X509Certificate[] chain, String authType)
+                    throws CertificateException {
+            }
+
+            @Override
+            public X509Certificate[] getAcceptedIssuers() {
+                return new X509Certificate[0];
+            }
+        };
+    }
+
+    @Bean
+    public SSLSocketFactory sslSocketFactory() {
+        try {
+            // 信任任何链接
+            SSLContext sslContext = SSLContext.getInstance("TLS");
+            sslContext.init(null, new TrustManager[]{x509TrustManager()}, new SecureRandom());
+            return sslContext.getSocketFactory();
+        } catch (NoSuchAlgorithmException | KeyManagementException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    @Bean
+    public ConnectionPool pool() {
+        return new ConnectionPool(maxIdleConnections, keepAliveDuration, TimeUnit.SECONDS);
+    }
+}

+ 28 - 0
src/main/java/com/zhili/dashboard/config/PropertyConfig.java

@@ -0,0 +1,28 @@
+package com.zhili.dashboard.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * 项目名称:scm
+ * 类 名 称:ApplicationConfig
+ * 类 描 述:应用配置文件定义类
+ * 创建时间:2020-09-15 13:20
+ *
+ * @author louis
+ */
+@Component
+public class PropertyConfig {
+
+    private static String linkUrl;
+
+    public static String getLinkUrl() {
+        return linkUrl;
+    }
+
+    @Value("${hz.mail.linkUrl:}")
+    public void setLinkUrl(String linkUrl) {
+        PropertyConfig.linkUrl = linkUrl;
+    }
+
+}

+ 79 - 0
src/main/java/com/zhili/dashboard/config/RedisConfig.java

@@ -0,0 +1,79 @@
+package com.zhili.dashboard.config;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+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.core.script.DefaultRedisScript;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * redis配置
+ * 
+ * @author user
+ */
+@Configuration
+@EnableCaching
+public class RedisConfig extends CachingConfigurerSupport
+{
+    @Bean
+    @SuppressWarnings(value = { "unchecked", "rawtypes" })
+    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
+    {
+        RedisTemplate<Object, Object> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
+        serializer.setObjectMapper(mapper);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+        template.setValueSerializer(serializer);
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(serializer);
+
+        template.afterPropertiesSet();
+        return template;
+    }
+
+    @Bean
+    public DefaultRedisScript<Long> limitScript()
+    {
+        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
+        redisScript.setScriptText(limitScriptText());
+        redisScript.setResultType(Long.class);
+        return redisScript;
+    }
+
+    /**
+     * 限流脚本
+     */
+    private String limitScriptText()
+    {
+        return "local key = KEYS[1]\n" +
+                "local count = tonumber(ARGV[1])\n" +
+                "local time = tonumber(ARGV[2])\n" +
+                "local current = redis.call('get', key);\n" +
+                "if current and tonumber(current) > count then\n" +
+                "    return current;\n" +
+                "end\n" +
+                "current = redis.call('incr', key)\n" +
+                "if tonumber(current) == 1 then\n" +
+                "    redis.call('expire', key, time)\n" +
+                "end\n" +
+                "return current;";
+    }
+}

+ 36 - 0
src/main/java/com/zhili/dashboard/config/ResourcesConfig.java

@@ -0,0 +1,36 @@
+package com.zhili.dashboard.config;
+
+import com.zhili.dashboard.base.Constants;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * 通用配置
+ *
+ * @author user
+ */
+@Configuration
+public class ResourcesConfig implements WebMvcConfigurer {
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        /** 本地文件上传路径 */
+        registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**").addResourceLocations("file:" + HzConfig.getProfile() + "/");
+    }
+
+    /**
+     * 自定义拦截规则
+     */
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        //registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
+    }
+}

+ 31 - 0
src/main/java/com/zhili/dashboard/config/SecurityConfig.java

@@ -0,0 +1,31 @@
+package com.zhili.dashboard.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * spring security配置
+ *
+ * @author user
+ */
+@Configuration
+public class SecurityConfig {
+
+    // 当前跨域请求最大有效时长。这里默认1天
+    private static final long MAX_AGE = 24 * 60 * 60 * 10;
+
+    @Bean
+    public CorsFilter corsFilter() {
+        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        CorsConfiguration corsConfiguration = new CorsConfiguration();
+        corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址
+        corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
+        corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
+        corsConfiguration.setMaxAge(MAX_AGE);
+        source.registerCorsConfiguration("/**", corsConfiguration); // 4 对接口配置跨域设置
+        return new CorsFilter(source);
+    }
+}

+ 135 - 0
src/main/java/com/zhili/dashboard/config/SwaggerConfig.java

@@ -0,0 +1,135 @@
+package com.zhili.dashboard.config;
+
+import io.swagger.annotations.ApiOperation;
+import io.swagger.models.auth.In;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.*;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.service.contexts.SecurityContext;
+import springfox.documentation.spring.web.plugins.Docket;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Swagger2的接口配置
+ *
+ * @author user
+ */
+@Configuration
+public class SwaggerConfig extends WebMvcConfigurationSupport {
+    /**
+     * 系统基础配置
+     */
+    @Autowired
+    private HzConfig hzConfig;
+
+    /**
+     * 是否开启swagger
+     */
+    @Value("${swagger.enabled}")
+    private boolean enabled;
+
+    /**
+     * 设置请求的统一前缀
+     */
+    @Value("${swagger.pathMapping}")
+    private String pathMapping;
+
+    /**
+     * 创建API
+     */
+    @Bean
+    public Docket createRestApi() {
+        return new Docket(DocumentationType.OAS_30)
+                // 是否启用Swagger
+                .enable(enabled)
+                // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
+                .apiInfo(apiInfo())
+                // 设置哪些接口暴露给Swagger展示
+                .select()
+                // 扫描所有有注解的api,用这种方式更灵活
+                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
+                // 扫描指定包中的swagger注解
+                //.apis(RequestHandlerSelectors.basePackage("com.hz.business.controller"))
+                // 扫描所有 .apis(RequestHandlerSelectors.any())
+                .paths(PathSelectors.any())
+                .build()
+                /* 设置安全模式,swagger可以设置访问token */
+                .securitySchemes(securitySchemes())
+                .securityContexts(securityContexts())
+                .pathMapping(pathMapping);
+    }
+
+    /**
+     * 安全模式,这里指定token通过Authorization头请求头传递
+     */
+    private List<SecurityScheme> securitySchemes() {
+        List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
+        apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
+        return apiKeyList;
+    }
+
+    /**
+     * 安全上下文
+     */
+    private List<SecurityContext> securityContexts() {
+        List<SecurityContext> securityContexts = new ArrayList<>();
+        securityContexts.add(
+                SecurityContext.builder()
+                        .securityReferences(defaultAuth())
+                        .operationSelector(o -> o.requestMappingPattern().matches("/.*"))
+                        .build());
+        return securityContexts;
+    }
+
+    /**
+     * 默认的安全上引用
+     */
+    private List<SecurityReference> defaultAuth() {
+        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
+        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
+        authorizationScopes[0] = authorizationScope;
+        List<SecurityReference> securityReferences = new ArrayList<>();
+        securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
+        return securityReferences;
+    }
+
+    /**
+     * 添加摘要信息
+     */
+    private ApiInfo apiInfo() {
+        // 用ApiInfoBuilder进行定制
+        return new ApiInfoBuilder()
+                // 设置标题
+                .title("标题:整车监控预警与性能分析平台_接口文档")
+                // 描述
+                .description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
+                // 作者信息
+                .contact(new Contact(hzConfig.getName(), null, null))
+                // 版本
+                .version("版本号:" + hzConfig.getVersion())
+                .build();
+    }
+
+    /**
+     * 重点
+     * @param registry
+     * @return void
+     */
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        registry.addResourceHandler("/swagger-ui/**")
+                .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
+                .resourceChain(false);
+    }
+
+}

+ 66 - 0
src/main/java/com/zhili/dashboard/config/ThreadPoolConfig.java

@@ -0,0 +1,66 @@
+package com.zhili.dashboard.config;
+
+import com.zhili.dashboard.utils.Threads;
+import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * 线程池配置
+ *
+ * @author user
+ **/
+@Configuration
+public class ThreadPoolConfig {
+    /**
+     * 核心线程池大小
+     */
+    private final int corePoolSize = 50;
+
+    /**
+     * 最大可创建的线程数
+     */
+    private final int maxPoolSize = 200;
+
+    /**
+     * 队列最大长度
+     */
+    private final int queueCapacity = 1000;
+
+    /**
+     * 线程池维护线程所允许的空闲时间
+     */
+    private final int keepAliveSeconds = 300;
+
+    @Bean(name = "threadPoolTaskExecutor")
+    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setMaxPoolSize(maxPoolSize);
+        executor.setCorePoolSize(corePoolSize);
+        executor.setQueueCapacity(queueCapacity);
+        executor.setKeepAliveSeconds(keepAliveSeconds);
+        // 线程池对拒绝任务(无线程可用)的处理策略
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        return executor;
+    }
+
+    /**
+     * 执行周期性或定时任务
+     */
+    @Bean(name = "scheduledExecutorService")
+    protected ScheduledExecutorService scheduledExecutorService() {
+        return new ScheduledThreadPoolExecutor(corePoolSize,
+                new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build()) {
+            @Override
+            protected void afterExecute(Runnable r, Throwable t) {
+                super.afterExecute(r, t);
+                Threads.printException(r, t);
+            }
+        };
+    }
+}

+ 173 - 0
src/main/java/com/zhili/dashboard/controller/AlarmMsgController.java

@@ -0,0 +1,173 @@
+package com.zhili.dashboard.controller;
+
+
+import com.zhili.dashboard.base.*;
+import com.zhili.dashboard.entity.CmdDetail;
+import com.zhili.dashboard.req.MapParam;
+import com.zhili.dashboard.req.ProvinceParam;
+import com.zhili.dashboard.req.RadarParam;
+import com.zhili.dashboard.service.IAlarmMsgService;
+import com.zhili.dashboard.vo.*;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 故障信息表
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Api(tags = "故障信息表")
+@RestController
+@RequestMapping("/dashboard/alarmMsg")
+public class AlarmMsgController {
+
+    @Resource
+    IAlarmMsgService alarmMsgService;
+
+    //@Cacheable(cacheNames = "gatewayHandler", key = "'getGatewayHandler'")
+    @ApiOperation("报警统计")
+    @GetMapping("/level/{type}")
+    public AjaxResult getAlarmLevelPie(@PathVariable("type") Integer type) {
+        List<BaseCycleChartVo> result = alarmMsgService.getAlarmLevelPie(type);
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("故障预警历史信息-24小时")
+    @GetMapping("/history/day")
+    public AjaxResult getAlarmHistoryLineForDay() {
+        BaseLineDecimalVo result = alarmMsgService.getAlarmHistoryLineForDay();
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("故障预警历史信息-30天")
+    @GetMapping("/history/month")
+    public AjaxResult getAlarmHistoryLineForMonth() {
+        BaseLineDecimalVo result = alarmMsgService.getAlarmHistoryLineForMonth();
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("高危用户列表")
+    @GetMapping("/highRisk")
+    public AjaxResult getHighRisk() {
+        List<HighRiskVo> result = alarmMsgService.getHighRisk();
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("风险等级电池统计信息")
+    @GetMapping("/riskList")
+    public AjaxResult getRiskList() {
+        List<RiskListVo> result = alarmMsgService.getRiskList();
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("故障电池与正常电池统计信息")
+    @GetMapping("/faultList")
+    public AjaxResult getFaultList() {
+        List<BaseCycleChartVo> result = alarmMsgService.getFaultList();
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("在线电池统计信息")
+    @GetMapping("/onLine")
+    public AjaxResult getOnLine() {
+        OnLineVo result = alarmMsgService.getOnLine();
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("电池状态统计信息")
+    @GetMapping("/deviceStatusList")
+    public AjaxResult getDeviceStatusList() {
+        BaseLineDecimalVo result = alarmMsgService.getDeviceStatusList();
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("区域电池信息排名")
+    @PostMapping("/districtOrder")
+    public AjaxResult getDistrictOrder(@RequestBody ProvinceParam param) {
+        List<SceneGroupVo> result = alarmMsgService.getDistrictOrder(param);
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("应用场景电池信息")
+    @PostMapping("/sceneGroup")
+    public AjaxResult getSceneGroup(@RequestBody ProvinceParam param) {
+        List<SceneGroupVo> result = alarmMsgService.getSceneGroup(param);
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("累计安全拦截次数&安全运行时长")
+    @GetMapping("/safeguard")
+    public AjaxResult getSafeguard() {
+        SafeguardVo result = alarmMsgService.getSafeguard();
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("累计信息统计")
+    @GetMapping("/cumulativeInfo")
+    public AjaxResult getCumulativeInfo() {
+        CumulativeInfoVo result = alarmMsgService.getCumulativeInfo();
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("累计循环次数")
+    @GetMapping("/cumulativeCycle")
+    public AjaxResult getCumulativeCycle() {
+        Long result = alarmMsgService.getCumulativeCycle();
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("电池详情")
+    @GetMapping("/detail/{id}")
+    public AjaxResult getDetail(@PathVariable("id") Long id) {
+        AlarmDetailVo result = alarmMsgService.getDetail(id);
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("雷达图")
+    @PostMapping("/radar")
+    public AjaxResult getRadar(@RequestBody RadarParam param) {
+        KindValueDoubleListVo result = alarmMsgService.getRadar(param);
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("地图信息")
+    @PostMapping("/batteryMap")
+    public AjaxResult getBatteryMap(@RequestBody MapParam param) {
+        List<BatteryMapVo> result = alarmMsgService.getBatteryMap(param);
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("安全事故率")
+    @PostMapping("/faultRate")
+    public AjaxResult getFaultRate(@RequestBody MapParam param) {
+        BigDecimal result = alarmMsgService.getFaultRate(param);
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("安全事故列表")
+    @PostMapping("/faultRateList")
+    public AjaxResult getFaultRateList(@RequestBody MapParam param) {
+        BaseLineDecimalVo result = alarmMsgService.getFaultRateList(param);
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("安全明细")
+    @GetMapping("/cmdDetailList")
+    public AjaxResult getCmdDetailList() {
+        List<CmdDetail> result = alarmMsgService.getCmdDetailList();
+        return AjaxResult.success(result);
+    }
+
+    @ApiOperation("安全概览")
+    @GetMapping("/cmdOverview")
+    public AjaxResult getCmdOverview() {
+        List<BaseCycleChartVo> result = alarmMsgService.getCmdOverview();
+        return AjaxResult.success(result);
+    }
+}

+ 19 - 0
src/main/java/com/zhili/dashboard/controller/CommandController.java

@@ -0,0 +1,19 @@
+package com.zhili.dashboard.controller;
+
+import io.swagger.annotations.Api;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 电池命令下发数据
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Api(tags = "电池命令下发数据")
+@RestController
+@RequestMapping("/dashboard/command")
+public class CommandController {
+
+}

+ 32 - 0
src/main/java/com/zhili/dashboard/controller/DeviceController.java

@@ -0,0 +1,32 @@
+package com.zhili.dashboard.controller;
+
+
+import com.zhili.dashboard.base.AjaxResult;
+import com.zhili.dashboard.base.BaseCycleChartVo;
+import com.zhili.dashboard.service.IDeviceService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * 设备信息
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Api(tags = "设备信息")
+@RestController
+@RequestMapping("/dashboard/device")
+public class DeviceController {
+
+    @Resource
+    IDeviceService deviceService;
+
+
+}

+ 20 - 0
src/main/java/com/zhili/dashboard/controller/DeviceDurationController.java

@@ -0,0 +1,20 @@
+package com.zhili.dashboard.controller;
+
+
+import io.swagger.annotations.Api;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 电池析锂时长统计信息
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Api(tags = "电池析锂时长统计信息")
+@RestController
+@RequestMapping("/dashboard/deviceDuration")
+public class DeviceDurationController {
+
+}

+ 20 - 0
src/main/java/com/zhili/dashboard/controller/OrgController.java

@@ -0,0 +1,20 @@
+package com.zhili.dashboard.controller;
+
+
+import io.swagger.annotations.Api;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 组织机构
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Api(tags = "组织机构")
+@RestController
+@RequestMapping("/dashboard/org")
+public class OrgController {
+
+}

+ 20 - 0
src/main/java/com/zhili/dashboard/controller/StatisticsController.java

@@ -0,0 +1,20 @@
+package com.zhili.dashboard.controller;
+
+
+import io.swagger.annotations.Api;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 电池数量&累计充放电总量统计
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Api(tags = "电池数量&累计充放电总量统计")
+@RestController
+@RequestMapping("/dashboard/statistics")
+public class StatisticsController {
+
+}

+ 84 - 0
src/main/java/com/zhili/dashboard/entity/AlarmMsg.java

@@ -0,0 +1,84 @@
+package com.zhili.dashboard.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import com.zhili.dashboard.base.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 云控信息表
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("t_alarm_msg")
+@ApiModel(value="AlarmMsg对象", description="云控信息表")
+public class AlarmMsg extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "设备编号")
+    private String sn;
+
+    @ApiModelProperty(value = "故障等级")
+    private Integer faultLevel;
+
+    @ApiModelProperty(value = "故障发生时间")
+    private LocalDateTime faultTime;
+
+    @ApiModelProperty(value = "机构id")
+    private String organId;
+
+    @ApiModelProperty(value = "故障编码")
+    private String faultCode;
+
+    @ApiModelProperty(value = "故障类型 2-低电量(编码58) 3-离线(编码59) 1-常规故障(编码非58、59)")
+    private Integer type;
+
+    @ApiModelProperty(value = "报警信息")
+    private String faultInfo;
+
+    @ApiModelProperty(value = "数据来源1-系统 2-客服")
+    private Integer source;
+
+    @ApiModelProperty(value = "处理时间")
+    private LocalDateTime finishTime;
+
+    @ApiModelProperty(value = "信息状态:0-未处理,1-已处理")
+    private Integer faultStatus;
+
+    @ApiModelProperty(value = "说明")
+    private String remark;
+
+    @ApiModelProperty(value = "处理建议")
+    private String faultAdvice;
+
+    @ApiModelProperty(value = "快充比例")
+    private BigDecimal fastCharge;
+
+    @ApiModelProperty(value = "项目名称")
+    @TableField(exist = false)
+    private String item;
+
+    @ApiModelProperty(value = "项目数量")
+    @TableField(exist = false)
+    private Integer num;
+
+    @ApiModelProperty(value = "数量")
+    @TableField(exist = false)
+    private Long quantity;
+
+    @ApiModelProperty(value = "源id")
+    private Long sid;
+}

+ 83 - 0
src/main/java/com/zhili/dashboard/entity/AlarmMsgWarn.java

@@ -0,0 +1,83 @@
+package com.zhili.dashboard.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.zhili.dashboard.base.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 云控信息表
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("t_alarm_msg_warn")
+@ApiModel(value="AlarmMsgWarn对象", description="云控信息表")
+public class AlarmMsgWarn extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "设备编号")
+    private String sn;
+
+    @ApiModelProperty(value = "故障等级")
+    private Integer faultLevel;
+
+    @ApiModelProperty(value = "故障发生时间")
+    private LocalDateTime faultTime;
+
+    @ApiModelProperty(value = "机构id")
+    private String organId;
+
+    @ApiModelProperty(value = "故障编码")
+    private String faultCode;
+
+    @ApiModelProperty(value = "故障类型 2-低电量(编码58) 3-离线(编码59) 1-常规故障(编码非58、59)")
+    private Integer type;
+
+    @ApiModelProperty(value = "报警信息")
+    private String faultInfo;
+
+    @ApiModelProperty(value = "数据来源1-系统 2-客服")
+    private Integer source;
+
+    @ApiModelProperty(value = "处理时间")
+    private LocalDateTime finishTime;
+
+    @ApiModelProperty(value = "信息状态:0-未处理,1-已处理")
+    private Integer faultStatus;
+
+    @ApiModelProperty(value = "说明")
+    private String remark;
+
+    @ApiModelProperty(value = "处理建议")
+    private String faultAdvice;
+
+    @ApiModelProperty(value = "快充比例")
+    private BigDecimal fastCharge;
+
+    @ApiModelProperty(value = "项目名称")
+    @TableField(exist = false)
+    private String item;
+
+    @ApiModelProperty(value = "项目数量")
+    @TableField(exist = false)
+    private Integer num;
+
+    @ApiModelProperty(value = "数量")
+    @TableField(exist = false)
+    private Long quantity;
+
+    @ApiModelProperty(value = "源id")
+    private Long sid;
+}

+ 47 - 0
src/main/java/com/zhili/dashboard/entity/CmdDetail.java

@@ -0,0 +1,47 @@
+package com.zhili.dashboard.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * <p>
+ * 电池命令下发详情
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Data
+@TableName("t_cmd_detail")
+@ApiModel(value="CmdDetail对象", description="电池命令下发详情")
+public class CmdDetail {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "设备编号")
+    private String sn;
+
+    @ApiModelProperty(value = "故障等级")
+    private Integer faultLevel;
+
+    @ApiModelProperty(value = "预警名称")
+    private String faultName;
+
+    @ApiModelProperty(value = "预警时间")
+    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+    private Date warningTime;
+
+    @ApiModelProperty(value = "拦截时间")
+    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+    private Date actionTime;
+
+    @TableField(exist = false)
+    @ApiModelProperty(value = "简单编号")
+    private String simpleSn;
+}

+ 36 - 0
src/main/java/com/zhili/dashboard/entity/Command.java

@@ -0,0 +1,36 @@
+package com.zhili.dashboard.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.zhili.dashboard.base.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 电池命令下发数据
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("t_command")
+@ApiModel(value="Command对象", description="电池命令下发数据")
+public class Command extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "设备编号")
+    private String sn;
+
+    @ApiModelProperty(value = "命令信息")
+    private String command;
+
+    @ApiModelProperty(value = "命令执行状态 1-成功 0-失败")
+    private Integer cmdStatus;
+
+
+}

+ 82 - 0
src/main/java/com/zhili/dashboard/entity/Device.java

@@ -0,0 +1,82 @@
+package com.zhili.dashboard.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.zhili.dashboard.base.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 设备信息
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("t_device")
+@ApiModel(value="Device对象", description="设备信息")
+public class Device extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "当前状态 1-充电,2-运行,3-静置,4-离线")
+    private Integer status;
+
+    @ApiModelProperty(value = "运营场景 0-乘用车 1-重卡 2-低速车 3-储能 4-备用电源")
+    private Integer scene;
+
+    @ApiModelProperty(value = "sn号")
+    private String sn;
+
+    @ApiModelProperty(value = "机构id(运营商)")
+    private String organId;
+
+    @ApiModelProperty(value = "imei号")
+    private String imei;
+
+    @ApiModelProperty(value = "品牌")
+    private String producer;
+
+    @ApiModelProperty(value = "设备类型(1:产品, 2:配件)")
+    private Integer deviceType;
+
+    @ApiModelProperty(value = "产品/配件 类型(1:电池, 2:电动车 3:充电器")
+    private Integer productType;
+
+    @ApiModelProperty(value = "型号")
+    private String model;
+
+    @ApiModelProperty(value = "国家")
+    private String country;
+
+    @ApiModelProperty(value = "省")
+    private String province;
+
+    @ApiModelProperty(value = "市")
+    private String city;
+
+    @ApiModelProperty(value = "镇")
+    private String town;
+
+    @ApiModelProperty(value = "区")
+    private String district;
+
+    @ApiModelProperty(value = "经度")
+    private String longitude;
+
+    @ApiModelProperty(value = "纬度")
+    private String latitude;
+
+    @ApiModelProperty(value = "在线标识 0-离线 1-在线")
+    private Integer onlineFlag;
+
+    @ApiModelProperty(value = "源id")
+    private Long sid;
+
+    @ApiModelProperty(value = "电芯类型")
+    private String batteryCoreType;
+}

+ 37 - 0
src/main/java/com/zhili/dashboard/entity/DeviceDuration.java

@@ -0,0 +1,37 @@
+package com.zhili.dashboard.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import com.zhili.dashboard.base.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+
+/**
+ * <p>
+ * 电池析锂时长统计信息
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("t_device_duration")
+@ApiModel(value="DeviceDuration对象", description="电池析锂时长统计信息")
+public class DeviceDuration extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "电池编号")
+    private String sn;
+
+    @ApiModelProperty(value = "析锂时长")
+    private BigDecimal duration;
+
+    @ApiModelProperty(value = "源id")
+    private Long sid;
+}

+ 47 - 0
src/main/java/com/zhili/dashboard/entity/DistributionMap.java

@@ -0,0 +1,47 @@
+package com.zhili.dashboard.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.zhili.dashboard.base.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+
+/**
+ * <p>
+ * 电池状态信息表
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("tb_distribution_map")
+@ApiModel(value="DistributionMap对象", description="电池状态信息表")
+public class DistributionMap extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "车辆型号")
+    private String model;
+
+    @ApiModelProperty(value = "电池型号")
+    private String cellModel;
+
+    @ApiModelProperty(value = "电池包型号")
+    private String packModel;
+
+    @ApiModelProperty(value = "充电与用车状态值:0为充电,1为用车")
+    private Integer statFlg;
+
+    @ApiModelProperty(value = "统计小时")
+    private String statisHours;
+
+    @ApiModelProperty(value = "时间段内车辆数")
+    private BigDecimal carNum;
+
+    @ApiModelProperty(value = "分区字段(日)")
+    private String statisDate;
+}

+ 37 - 0
src/main/java/com/zhili/dashboard/entity/FaultMonthRate.java

@@ -0,0 +1,37 @@
+package com.zhili.dashboard.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.zhili.dashboard.base.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 组织机构
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("t_fault_month_rate")
+@ApiModel(value="Org对象", description="安全事故率")
+public class FaultMonthRate extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "月份")
+    private String mon;
+
+    @ApiModelProperty(value = "事故率")
+    private String rate;
+
+    @ApiModelProperty(value = "事故数量")
+    private Integer num;
+
+    @ApiModelProperty(value = "当前车辆(万台)")
+    private Integer numCurrent;
+}

+ 52 - 0
src/main/java/com/zhili/dashboard/entity/Model.java

@@ -0,0 +1,52 @@
+package com.zhili.dashboard.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.zhili.dashboard.base.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+
+/**
+ * 模型对象 t_model
+ *
+ * @author hz
+ * @date 2022-02-25
+ */
+@Data
+@TableName("algo_list")
+@EqualsAndHashCode(callSuper = true)
+@ApiModel(value = "Model对象", description = "模型")
+public class Model extends BaseEntity implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "算法id")
+    private Long algoId;
+
+    @ApiModelProperty(value = "模型名称")
+    private String algoName;
+
+    @ApiModelProperty(value = "告警等级0~5")
+    private Integer faultLevel;
+
+    @ApiModelProperty(value = "模型编码")
+    private String faultCode;
+
+    @ApiModelProperty(value = "模型状态 0-停用 1-启用")
+    private Integer isActivate;
+
+    @ApiModelProperty(value = "算法其他公共参数(不可调参数)")
+    private String globalParam;
+
+    @ApiModelProperty(value = "故障影响分析")
+    private String faultInfluence;
+
+    @ApiModelProperty(value = "模型类型")
+    private Integer modelType;
+
+    @ApiModelProperty(value = "算法参数是否可配(0不可配,1可配)")
+    private String configurableFlag;
+}

+ 31 - 0
src/main/java/com/zhili/dashboard/entity/Online.java

@@ -0,0 +1,31 @@
+package com.zhili.dashboard.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 在线电池统计
+ *
+ * @author hz
+ * @date 2022-02-25
+ */
+@Data
+@TableName("dw_online_vin_cnt")
+@ApiModel(value = "Online对象", description = "在线电池统计")
+public class Online implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "id")
+    private Long id;
+
+    @ApiModelProperty(value = "时间点")
+    private String timeInfo;
+
+    @ApiModelProperty(value = "统计数据")
+    private String data;
+}

+ 42 - 0
src/main/java/com/zhili/dashboard/entity/Org.java

@@ -0,0 +1,42 @@
+package com.zhili.dashboard.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.zhili.dashboard.base.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 组织机构
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("t_org")
+@ApiModel(value="Org对象", description="组织机构")
+public class Org extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "机构ID")
+    private String orgId;
+
+    @ApiModelProperty(value = "组织机构名称")
+    private String orgName;
+
+    @ApiModelProperty(value = "上级")
+    private Integer parentId;
+
+    @ApiModelProperty(value = "组织机构编码,逐级加长")
+    private String orgCode;
+
+    @ApiModelProperty(value = "级别")
+    private Integer orgLevel;
+
+
+}

+ 35 - 0
src/main/java/com/zhili/dashboard/entity/Statistics.java

@@ -0,0 +1,35 @@
+package com.zhili.dashboard.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.time.LocalDateTime;
+
+import com.zhili.dashboard.base.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 电池数量&累计充放电总量统计
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("t_statistics")
+@ApiModel(value="Statistics对象", description="电池数量&累计充放电总量统计")
+public class Statistics extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "统计时间")
+    private LocalDateTime dataInfo;
+
+    @ApiModelProperty(value = "统计信息json字符串")
+    private String infoJson;
+
+
+}

+ 46 - 0
src/main/java/com/zhili/dashboard/enums/AlarmCoreTypeEnum.java

@@ -0,0 +1,46 @@
+package com.zhili.dashboard.enums;
+
+/**
+ * @author zyg
+ * @className AlarmCoreTypeEnum
+ * @date 2021年12月02日 11:15
+ */
+public enum AlarmCoreTypeEnum {
+
+    /**
+     * 电芯类型 B-磷酸铁锂 E-三元锂电
+     */
+    LEVEL_ONE("B", "磷酸铁锂"),
+    LEVEL_TWO("E", "三元锂电"),
+    ;
+
+    private final String code;
+    private final String message;
+
+    AlarmCoreTypeEnum(String code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public boolean isEqual(String code) {
+        return this.code.equals(code);
+    }
+
+    public static String getDesc(String code) {
+        AlarmCoreTypeEnum[] enums = values();
+        for (AlarmCoreTypeEnum en : enums) {
+            if (en.code().equals(code)) {
+                return en.message();
+            }
+        }
+        return null;
+    }
+
+    public String code() {
+        return this.code;
+    }
+
+    public String message() {
+        return this.message;
+    }
+}

+ 46 - 0
src/main/java/com/zhili/dashboard/enums/AlarmFaultStatusEnum.java

@@ -0,0 +1,46 @@
+package com.zhili.dashboard.enums;
+
+/**
+ * @author zyg
+ * @className DeviceStatusEnum
+ * @date 2021年12月02日 11:15
+ */
+public enum AlarmFaultStatusEnum {
+
+    /**
+     * 当前状态 1-充电,2-运行,3-静置,4-离线
+     */
+    DONE(1, "已修复"),
+    RUN(0, "未处理"),
+    ;
+
+    private final int code;
+    private final String message;
+
+    AlarmFaultStatusEnum(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public boolean isEqual(int code) {
+        return this.code == code;
+    }
+
+    public static String getDesc(Integer code) {
+        AlarmFaultStatusEnum[] enums = values();
+        for (AlarmFaultStatusEnum en : enums) {
+            if (en.code().equals(code)) {
+                return en.message();
+            }
+        }
+        return null;
+    }
+
+    public Integer code() {
+        return this.code;
+    }
+
+    public String message() {
+        return this.message;
+    }
+}

+ 49 - 0
src/main/java/com/zhili/dashboard/enums/AlarmLevelEnum.java

@@ -0,0 +1,49 @@
+package com.zhili.dashboard.enums;
+
+/**
+ * @author zyg
+ * @className AlarmLevelEnum
+ * @date 2021年12月02日 11:15
+ */
+public enum AlarmLevelEnum {
+
+    /**
+     * 状态:充电状态(1-一级报警 2-二级报警 3-三级报警 4-四级报警 5-五级报警
+     */
+    LEVEL_ONE(1, "一级报警"),
+    LEVEL_TWO(2, "二级报警"),
+    LEVEL_THREE(3, "三级报警"),
+    LEVEL_FOUR(4, "四级报警"),
+    LEVEL_FIVE(5, "五级报警"),
+    ;
+
+    private final int code;
+    private final String message;
+
+    AlarmLevelEnum(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public boolean isEqual(int code) {
+        return this.code == code;
+    }
+
+    public static String getDesc(Integer code) {
+        AlarmLevelEnum[] enums = values();
+        for (AlarmLevelEnum en : enums) {
+            if (en.code().equals(code)) {
+                return en.message();
+            }
+        }
+        return null;
+    }
+
+    public Integer code() {
+        return this.code;
+    }
+
+    public String message() {
+        return this.message;
+    }
+}

+ 47 - 0
src/main/java/com/zhili/dashboard/enums/AlarmLevelGroupEnum.java

@@ -0,0 +1,47 @@
+package com.zhili.dashboard.enums;
+
+/**
+ * @author zyg
+ * @className AlarmLevelGroupEnum
+ * @date 2021年12月02日 11:15
+ */
+public enum AlarmLevelGroupEnum {
+
+    /**
+     * 状态:风险等级 0-高风险预警 1-中风险预警 2-低风险预警
+     */
+    HIGH(0, "高风险预警"),
+    MIDDLE(1, "中风险预警"),
+    LOW(2, "低风险预警"),
+    ;
+
+    private final int code;
+    private final String message;
+
+    AlarmLevelGroupEnum(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public boolean isEqual(int code) {
+        return this.code == code;
+    }
+
+    public static String getDesc(Integer code) {
+        AlarmLevelGroupEnum[] enums = values();
+        for (AlarmLevelGroupEnum en : enums) {
+            if (en.code().equals(code)) {
+                return en.message();
+            }
+        }
+        return null;
+    }
+
+    public Integer code() {
+        return this.code;
+    }
+
+    public String message() {
+        return this.message;
+    }
+}

+ 47 - 0
src/main/java/com/zhili/dashboard/enums/BatteryDataTypeEnum.java

@@ -0,0 +1,47 @@
+package com.zhili.dashboard.enums;
+
+/**
+ * @author zyg
+ * @className BatteryDataTypeEnum
+ * @date 2021年12月02日 11:15
+ */
+public enum BatteryDataTypeEnum {
+
+    /**
+     * 状态:数据类型 1-报警率 2-电池数 3-预警率
+     */
+    Alarm(1, "报警率"),
+    BATTERY(2, "电池数"),
+    WARN(3, "预警率"),
+    ;
+
+    private final int code;
+    private final String message;
+
+    BatteryDataTypeEnum(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public boolean isEqual(int code) {
+        return this.code == code;
+    }
+
+    public static String getDesc(Integer code) {
+        BatteryDataTypeEnum[] enums = values();
+        for (BatteryDataTypeEnum en : enums) {
+            if (en.code().equals(code)) {
+                return en.message();
+            }
+        }
+        return null;
+    }
+
+    public Integer code() {
+        return this.code;
+    }
+
+    public String message() {
+        return this.message;
+    }
+}

+ 51 - 0
src/main/java/com/zhili/dashboard/enums/BatteryStatusEnum.java

@@ -0,0 +1,51 @@
+package com.zhili.dashboard.enums;
+
+/**
+ * @author zyg
+ * @className DeviceFaultStatusEnum
+ * @date 2021年12月02日 11:15
+ */
+public enum BatteryStatusEnum {
+
+    /**
+     * 状态:电池状态 0x00:运行;0x01:睡眠;0x02:快充;0x03:慢充;“0xFE”表示异常,“0xFF”表示无效。
+     */
+    RUN(0, "运行"),
+    SLEEP(1, "睡眠"),
+    FAST(2, "快充"),
+    SLOW(3, "慢充"),
+    OTHER(4, "其他"),
+    EXCEPTION(254, "异常"),
+    INVALID(255, "无效"),
+    ;
+
+    private final int code;
+    private final String message;
+
+    BatteryStatusEnum(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public boolean isEqual(int code) {
+        return this.code == code;
+    }
+
+    public static String getDesc(Integer code) {
+        BatteryStatusEnum[] enums = values();
+        for (BatteryStatusEnum en : enums) {
+            if (en.code().equals(code)) {
+                return en.message();
+            }
+        }
+        return null;
+    }
+
+    public Integer code() {
+        return this.code;
+    }
+
+    public String message() {
+        return this.message;
+    }
+}

+ 48 - 0
src/main/java/com/zhili/dashboard/enums/DeviceStatusEnum.java

@@ -0,0 +1,48 @@
+package com.zhili.dashboard.enums;
+
+/**
+ * @author zyg
+ * @className DeviceStatusEnum
+ * @date 2021年12月02日 11:15
+ */
+public enum DeviceStatusEnum {
+
+    /**
+     * 当前状态 1-充电,2-运行,3-静置,4-离线
+     */
+    CHARGE(1, "充电"),
+    RUN(2, "运行"),
+    SLEEP(3, "静置"),
+    OFF(4, "离线"),
+    ;
+
+    private final int code;
+    private final String message;
+
+    DeviceStatusEnum(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public boolean isEqual(int code) {
+        return this.code == code;
+    }
+
+    public static String getDesc(Integer code) {
+        DeviceStatusEnum[] enums = values();
+        for (DeviceStatusEnum en : enums) {
+            if (en.code().equals(code)) {
+                return en.message();
+            }
+        }
+        return null;
+    }
+
+    public Integer code() {
+        return this.code;
+    }
+
+    public String message() {
+        return this.message;
+    }
+}

+ 49 - 0
src/main/java/com/zhili/dashboard/enums/SceneEnum.java

@@ -0,0 +1,49 @@
+package com.zhili.dashboard.enums;
+
+/**
+ * @author zyg
+ * @className SceneEnum
+ * @date 2021年12月02日 11:15
+ */
+public enum SceneEnum {
+
+    /**
+     * 运营场景 0-乘用车 1-重卡 2-低速车 3-储能 4-备用电源
+     */
+    CAR(0, "乘用车"),
+    HEIGHT(1, "重卡"),
+    LOW(2, "低速车"),
+    SAVE(3, "储能"),
+    BAK(4, "备用电源"),
+    ;
+
+    private final int code;
+    private final String message;
+
+    SceneEnum(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public boolean isEqual(int code) {
+        return this.code == code;
+    }
+
+    public static String getDesc(Integer code) {
+        SceneEnum[] enums = values();
+        for (SceneEnum en : enums) {
+            if (en.code().equals(code)) {
+                return en.message();
+            }
+        }
+        return null;
+    }
+
+    public Integer code() {
+        return this.code;
+    }
+
+    public String message() {
+        return this.message;
+    }
+}

+ 177 - 0
src/main/java/com/zhili/dashboard/gen/CodeGenerator.java

@@ -0,0 +1,177 @@
+package com.zhili.dashboard.gen;
+
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.AutoGenerator;
+import com.baomidou.mybatisplus.generator.InjectionConfig;
+import com.baomidou.mybatisplus.generator.config.*;
+import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
+import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
+
+import java.util.*;
+
+/**
+ * @author liuzezhong
+ * @title
+ * @date 2021/7/20
+ */
+public class CodeGenerator {
+
+    /**
+     * <p>
+     * 读取控制台内容
+     * </p>
+     */
+    public static String scanner(String tip) {
+        Scanner scanner = new Scanner(System.in);
+        StringBuilder help = new StringBuilder();
+        help.append("请输入" + tip + ":");
+        System.out.println(help.toString());
+        if (scanner.hasNext()) {
+            String ipt = scanner.next();
+            if (StringUtils.isNotBlank(ipt)) {
+                return ipt;
+            }
+        }
+        throw new MybatisPlusException("请输入正确的" + tip + "!");
+    }
+
+    public static void main(String[] args) {
+        // 代码生成器
+        AutoGenerator mpg = new AutoGenerator();
+
+        // 全局配置
+        GlobalConfig gc = new GlobalConfig();
+        String projectPath = System.getProperty("user.dir");
+        gc.setOutputDir(projectPath + "/src/main/java");
+        gc.setAuthor("zyg");
+        gc.setOpen(false);
+        gc.setSwagger2(true);
+        //实体属性 Swagger2 注解
+        mpg.setGlobalConfig(gc);
+
+        // 数据源配置
+        DataSourceConfig dsc = new DataSourceConfig();
+        dsc.setUrl("jdbc:mysql://192.168.0.40:3306/db_omes_dashboard?useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true");
+        // dsc.setSchemaName("public");
+        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
+        dsc.setUsername("root");
+        dsc.setPassword("Qx123456");
+        //类型转换
+        dsc.setTypeConvert(new ITypeConvert() {
+            @Override
+            public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
+                String t = fieldType.toLowerCase();
+                if(t.contains("datetime")){
+                    return DbColumnType.LOCAL_DATE_TIME;
+                }
+                if(t.contains("bigint")){
+                    return DbColumnType.LONG;
+                }
+                if (t.contains("tinyint")) {
+                    return DbColumnType.INTEGER;
+                }
+                //其它字段采用默认转换(非mysql数据库可以使用其它默认的数据库转换器)
+                return new MySqlTypeConvert().processTypeConvert(globalConfig,fieldType);
+            }
+        });
+        mpg.setDataSource(dsc);
+
+        // 包配置
+        PackageConfig pc = new PackageConfig();
+        pc.setModuleName(scanner("模块名"));
+        pc.setParent("com");
+        mpg.setPackageInfo(pc);
+
+        // 自定义配置
+        InjectionConfig cfg = new InjectionConfig() {
+            @Override
+            public void initMap() {
+                // to do nothing
+            }
+        };
+
+        // 如果模板引擎是 freemarker
+        String templatePath = "/templates/mapper.xml.ftl";
+        // 如果模板引擎是 velocity
+        // String templatePath = "/templates/mapper.xml.vm";
+
+        // 自定义输出配置
+        List<FileOutConfig> focList = new ArrayList<>();
+        // 自定义配置会被优先输出
+        focList.add(new FileOutConfig(templatePath) {
+            @Override
+            public String outputFile(TableInfo tableInfo) {
+                // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
+                return projectPath + "/src/main/resources/mapper/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
+            }
+        });
+        /*
+        cfg.setFileCreate(new IFileCreate() {
+            @Override
+            public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
+                // 判断自定义文件夹是否需要创建
+                checkDir("调用默认方法创建的目录,自定义目录用");
+                if (fileType == FileType.MAPPER) {
+                    // 已经生成 mapper 文件判断存在,不想重新生成返回 false
+                    return !new File(filePath).exists();
+                }
+                // 允许生成模板文件
+                return true;
+            }
+        });
+        */
+        cfg.setFileOutConfigList(focList);
+        mpg.setCfg(cfg);
+
+        // 配置模板
+        TemplateConfig templateConfig = new TemplateConfig();
+
+        // 配置自定义输出模板
+        //指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
+        // templateConfig.setEntity("templates/entity2.java");
+        // templateConfig.setService();
+        // templateConfig.setController();
+
+        templateConfig.setXml(null);
+        mpg.setTemplate(templateConfig);
+
+        // 策略配置
+        StrategyConfig strategy = new StrategyConfig();
+        strategy.setNaming(NamingStrategy.underline_to_camel);
+        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
+        strategy.setSuperEntityClass("com.base.BaseEntity");
+        //这里本来以为配置上 生成的实体类就没有父类的属性了,但其实不是。
+        //如何去掉父类属性,下面有说明。
+        strategy.setSuperEntityColumns("id","create_by","create_time","update_by","update_time","is_delete");
+        strategy.setEntityLombokModel(true);
+        strategy.setRestControllerStyle(true);
+        // 公共父类
+        //strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");
+        // 写于父类中的公共字段
+        strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
+        strategy.setControllerMappingHyphenStyle(true);
+        strategy.setTablePrefix("t_");
+        mpg.setStrategy(strategy);
+        InjectionConfig in = new InjectionConfig() {
+            @Override
+            public void initMap() {
+                Map<String, Object> map = new HashMap<>();
+                map.put("superColumns", this.getConfig().getStrategyConfig().getSuperEntityColumns());
+                this.setMap(map);
+            }
+        };
+        Map<String, Object> map1 = new HashMap<>();
+        map1.put("superColumns", strategy.getSuperEntityColumns());
+        in.setMap(map1);
+        mpg.setCfg(in);
+        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
+        mpg.execute();
+    }
+}

+ 27 - 0
src/main/java/com/zhili/dashboard/handler/ApplicationContextHolder.java

@@ -0,0 +1,27 @@
+package com.zhili.dashboard.handler;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Tianms
+ * @date 2019/8/13 16:48
+ * @description
+ */
+@Component
+public class ApplicationContextHolder implements ApplicationContextAware {
+
+    private static ApplicationContext context;
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        context = applicationContext;
+    }
+
+    public static ConfigurableApplicationContext get() {
+        return (ConfigurableApplicationContext) context;
+    }
+}

+ 33 - 0
src/main/java/com/zhili/dashboard/handler/AuthenticationEntryPointImpl.java

@@ -0,0 +1,33 @@
+//package com.handler;
+//
+//import com.alibaba.fastjson.JSON;
+//import com.base.AjaxResult;
+//import com.utils.HttpStatus;
+//import com.utils.ServletUtils;
+//import com.utils.StringUtils;
+//import org.springframework.security.core.AuthenticationException;
+//import org.springframework.security.web.AuthenticationEntryPoint;
+//import org.springframework.stereotype.Component;
+//
+//import javax.servlet.http.HttpServletRequest;
+//import javax.servlet.http.HttpServletResponse;
+//import java.io.IOException;
+//import java.io.Serializable;
+//
+///**
+// * 认证失败处理类 返回未授权
+// *
+// * @author user
+// */
+//@Component
+//public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable {
+//    private static final long serialVersionUID = -8970718410437077606L;
+//
+//    @Override
+//    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e)
+//            throws IOException {
+//        int code = HttpStatus.UNAUTHORIZED;
+//        String msg = StringUtils.format("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI());
+//        ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg)));
+//    }
+//}

+ 58 - 0
src/main/java/com/zhili/dashboard/handler/CustomMetaObjectHandler.java

@@ -0,0 +1,58 @@
+package com.zhili.dashboard.handler;
+
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import com.zhili.dashboard.base.UserInformationDTO;
+import com.zhili.dashboard.utils.GetUserInformationUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.reflection.MetaObject;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+
+/**
+ * @ClassName : MyMetaObjectHandler
+ * @Description : 自动插入数据
+ * @Component * 一定不要忘记把处理器加入到IOC容器中。
+ * @Author : zyg
+ * @Date: 2021-05-14 10:41
+ */
+@Slf4j
+@Component
+public class CustomMetaObjectHandler implements MetaObjectHandler {
+
+    /**
+     * 插入时候的填充策略
+     *
+     * @param metaObject 字段
+     */
+    @Override
+    public void insertFill(MetaObject metaObject) {
+        UserInformationDTO userBasic = GetUserInformationUtils.getUserBasic();
+        LocalDateTime now = LocalDateTime.now();
+        this.setFieldValByName("createTime", now, metaObject);
+        this.setFieldValByName("updateTime", now, metaObject);
+        if (null != userBasic) {
+            this.setFieldValByName("create_by", userBasic.getName(), metaObject);
+            this.setFieldValByName("update_by", userBasic.getName(), metaObject);
+        } else {
+            this.setFieldValByName("create_by", "系统自动执行", metaObject);
+            this.setFieldValByName("update_by", "系统自动执行", metaObject);
+        }
+    }
+
+    /**
+     * 更新时间的填充策略
+     */
+    @Override
+    public void updateFill(MetaObject metaObject) {
+        UserInformationDTO userBasic = GetUserInformationUtils.getUserBasic();
+        if (null != userBasic) {
+            this.setFieldValByName("create_by", userBasic.getName(), metaObject);
+        } else {
+            this.setFieldValByName("update_by", "系统自动执行", metaObject);
+        }
+        this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
+    }
+
+}
+

+ 42 - 0
src/main/java/com/zhili/dashboard/handler/JwtAuthenticationTokenFilter.java

@@ -0,0 +1,42 @@
+//package com.handler;
+//
+//import com.base.LoginUser;
+//import com.service.TokenService;
+//import com.utils.SecurityUtils;
+//import com.utils.StringUtils;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+//import org.springframework.security.core.context.SecurityContextHolder;
+//import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+//import org.springframework.stereotype.Component;
+//import org.springframework.web.filter.OncePerRequestFilter;
+//
+//import javax.servlet.FilterChain;
+//import javax.servlet.ServletException;
+//import javax.servlet.http.HttpServletRequest;
+//import javax.servlet.http.HttpServletResponse;
+//import java.io.IOException;
+//
+///**
+// * token过滤器 验证token有效性
+// *
+// * @author user
+// */
+//@Component
+//public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
+//    @Autowired
+//    private TokenService tokenService;
+//
+//    @Override
+//    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
+//            throws ServletException, IOException {
+//        LoginUser loginUser = tokenService.getLoginUser(request);
+//        if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication())) {
+//            tokenService.verifyToken(loginUser);
+//            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
+//            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+//            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
+//        }
+//        chain.doFilter(request, response);
+//    }
+//}

+ 52 - 0
src/main/java/com/zhili/dashboard/handler/LogoutSuccessHandlerImpl.java

@@ -0,0 +1,52 @@
+//package com.handler;
+//
+//import com.alibaba.fastjson.JSON;
+//import com.base.AjaxResult;
+//import com.base.Constants;
+//import com.base.LoginUser;
+//import com.service.TokenService;
+//import com.utils.HttpStatus;
+//import com.utils.ServletUtils;
+//import com.utils.StringUtils;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.security.core.Authentication;
+//import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
+//
+//import javax.servlet.ServletException;
+//import javax.servlet.http.HttpServletRequest;
+//import javax.servlet.http.HttpServletResponse;
+//import java.io.IOException;
+//
+///**
+// * 自定义退出处理类 返回成功
+// *
+// * @author user
+// */
+//@Configuration
+//public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler {
+//    @Autowired
+//    private TokenService tokenService;
+//
+//    /**
+//     * 退出处理
+//     *
+//     * @return
+//     */
+//    @Override
+//    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
+//            throws IOException, ServletException {
+//        LoginUser loginUser = tokenService.getLoginUser(request);
+//        if (StringUtils.isNotNull(loginUser)) {
+//            String userName = loginUser.getUsername();
+//            // 删除用户缓存记录
+//            tokenService.delLoginUser(loginUser.getToken());
+//            if (!loginUser.getUsername().equals("admin")) {
+//                tokenService.delParentToken(loginUser.getId());
+//            }
+//            // 记录用户退出日志
+//            //AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, "退出成功"));
+//        }
+//        ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(HttpStatus.SUCCESS, "退出成功")));
+//    }
+//}

+ 49 - 0
src/main/java/com/zhili/dashboard/handler/RepeatSubmitInterceptor.java

@@ -0,0 +1,49 @@
+//package com.zhili.dashboard.handler;
+//
+//import com.alibaba.fastjson.JSONObject;
+//import com.zhili.dashboard.annotation.RepeatSubmit;
+//import com.zhili.dashboard.base.AjaxResult;
+//import com.zhili.dashboard.utils.ServletUtils;
+//import org.springframework.stereotype.Component;
+//import org.springframework.web.method.HandlerMethod;
+//import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+//
+//import javax.servlet.http.HttpServletRequest;
+//import javax.servlet.http.HttpServletResponse;
+//import java.lang.reflect.Method;
+//
+///**
+// * 防止重复提交拦截器
+// *
+// * @author user
+// */
+//@Component
+//public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter {
+//    @Override
+//    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+//        if (handler instanceof HandlerMethod) {
+//            HandlerMethod handlerMethod = (HandlerMethod) handler;
+//            Method method = handlerMethod.getMethod();
+//            RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
+//            if (annotation != null) {
+//                if (this.isRepeatSubmit(request)) {
+//                    AjaxResult ajaxResult = AjaxResult.error("不允许重复提交,请稍后再试");
+//                    ServletUtils.renderString(response, JSONObject.toJSONString(ajaxResult));
+//                    return false;
+//                }
+//            }
+//            return true;
+//        } else {
+//            return super.preHandle(request, response, handler);
+//        }
+//    }
+//
+//    /**
+//     * 验证是否重复提交由子类实现具体的防重复提交的规则
+//     *
+//     * @param request
+//     * @return
+//     * @throws Exception
+//     */
+//    public abstract boolean isRepeatSubmit(HttpServletRequest request);
+//}

+ 163 - 0
src/main/java/com/zhili/dashboard/mapper/AlarmMsgMapper.java

@@ -0,0 +1,163 @@
+package com.zhili.dashboard.mapper;
+
+import com.zhili.dashboard.entity.AlarmMsg;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhili.dashboard.entity.Device;
+import com.zhili.dashboard.entity.DeviceDuration;
+import org.apache.ibatis.annotations.MapKey;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * 云控信息表 Mapper 接口
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+public interface AlarmMsgMapper extends BaseMapper<AlarmMsg> {
+
+    /**
+     * 按照故障等级分组查询
+     * @param dateStr 参数
+     * @return java.util.List<com.zhili.dashboard.entity.AlarmMsg>
+     */
+    public List<AlarmMsg> getAlarmLevelPie(@Param("dateStr") String dateStr);
+
+    /**
+     * 最近24小时故障数量统计
+     * @param dateStr 参数
+     * @return java.util.List<Map<String, Object>>
+     */
+    @MapKey("id")
+    public List<Map<String, Object>> getAlarmHistoryDay(@Param("dateStr") String dateStr);
+
+    /**
+     * 最近24小时故障完结量统计
+     * @param dateStr 参数
+     * @return java.util.List<Map<String, Object>>
+     */
+    @MapKey("id")
+    public List<Map<String, Object>> getAlarmHistoryDayOverRate(@Param("dateStr") String dateStr);
+
+    /**
+     * 最近30天故障数量统计
+     * @param dateStr 参数
+     * @return List<Map<String, Object>>
+     */
+    @MapKey("id")
+    public List<Map<String, Object>> getAlarmHistoryMonth(@Param("dateStr") String dateStr);
+
+    /**
+     * 最近30天故障完结率
+     * @param dateStr 参数
+     * @return List<Map<String, Object>>
+     */
+    @MapKey("id")
+    public List<Map<String, Object>> getAlarmHistoryOveMonthRate(@Param("dateStr") String dateStr);
+
+
+
+
+
+    /**
+     * 获取高危用户
+     * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
+     */
+    @MapKey("id")
+    public List<Map<String, Object>> getDeviceStatusGroup();
+
+    /**
+     * 在线电池统计
+     * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getOnLine();
+
+    /**
+     * 电池状态统计信息
+     * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getDeviceStatusList(@Param("dateStr") String dateStr);
+
+    /**
+     * 报警数量
+     * @param province 参数
+     * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getDistrictFaultOrder(@Param("province") String province);
+
+    /**
+     * 电池数量
+     * @param province 参数
+     * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getDistrictDeviceOrder(@Param("province") String province);
+
+    /**
+     * 电池数量
+     * @param province 参数
+     * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getDistrictDeviceOrderSix(@Param("province") String province);
+
+    /**
+     * 应用场景电池信息
+     * @param province 参数
+     * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getSceneFaultGroup(@Param("province") String province);
+
+    /**
+     * 应用场景电池信息
+     * @param province 参数
+     * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getSceneDeviceGroup(@Param("province") String province);
+
+    /**
+     * 安全运行时间
+     * @return java.lang.Integer
+     */
+    Long getInterval();
+
+    /**
+     * 累计信息统计  
+     * @return java.util.Map<java.lang.String,java.lang.Object>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getCumulativeInfo();
+
+    /**
+     * 电池详情
+     * @param id 参数
+     * @return List<Map<String, Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getDetail(@Param("id") Long id);
+
+    /**
+     * 雷达图
+     * @param sn 参数
+     * @return List<Map<String, Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getRadarItems(@Param("sn") String sn);
+
+    /**
+     * 电池地图
+     * @param province 参数
+     * @return List<Map<String, Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getBatteryMap(@Param("province") String province);
+}

+ 86 - 0
src/main/java/com/zhili/dashboard/mapper/AlarmMsgWarnMapper.java

@@ -0,0 +1,86 @@
+package com.zhili.dashboard.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhili.dashboard.entity.AlarmMsgWarn;
+import com.zhili.dashboard.req.ProvinceParam;
+import org.apache.ibatis.annotations.MapKey;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * 云控信息表 Mapper 接口
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+public interface AlarmMsgWarnMapper extends BaseMapper<AlarmMsgWarn> {
+
+    /**
+     * 获取高危用户
+     *
+     * @return java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
+     */
+    @MapKey("id")
+    public List<Map<String, Object>> getHighRisk();
+
+    /**
+     * 风险等级
+     *
+     * @return java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
+     */
+    @MapKey("id")
+    public List<Map<String, Object>> getAlarmLevelGroup();
+
+    /**
+     * 应用场景电池信息
+     * @param province 参数
+     * @return java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getSceneFaultGroup(@Param("province") String province);
+
+    /**
+     * 应用场景电池信息
+     * @param province 参数
+     * @return java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getSceneDeviceGroup(@Param("province") String province);
+
+    /**
+     * 电池地图
+     *
+     * @param province 参数
+     * @return List<Map < String, Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getBatteryMap(@Param("province") String province);
+
+    /**
+     * 电池数量
+     *
+     * @param province 参数
+     * @return java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getDistrictDeviceOrder(@Param("province") String province);
+
+    /**
+     * 报警数量
+     *
+     * @param province 参数
+     * @return java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getDistrictFaultOrder(@Param("province") String province);
+
+    /**
+     * 清理预警故障
+     * @return java.lang.Long
+     */
+    Long execUpdateStatus();
+}

+ 16 - 0
src/main/java/com/zhili/dashboard/mapper/CmdDetailMapper.java

@@ -0,0 +1,16 @@
+package com.zhili.dashboard.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhili.dashboard.entity.CmdDetail;
+
+/**
+ * <p>
+ * 电池命令下发数据 Mapper 接口
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+public interface CmdDetailMapper extends BaseMapper<CmdDetail> {
+
+}

+ 16 - 0
src/main/java/com/zhili/dashboard/mapper/CommandMapper.java

@@ -0,0 +1,16 @@
+package com.zhili.dashboard.mapper;
+
+import com.zhili.dashboard.entity.Command;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 电池命令下发数据 Mapper 接口
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+public interface CommandMapper extends BaseMapper<Command> {
+
+}

+ 16 - 0
src/main/java/com/zhili/dashboard/mapper/DeviceDurationMapper.java

@@ -0,0 +1,16 @@
+package com.zhili.dashboard.mapper;
+
+import com.zhili.dashboard.entity.DeviceDuration;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 电池状态统计信息 Mapper 接口
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+public interface DeviceDurationMapper extends BaseMapper<DeviceDuration> {
+
+}

+ 16 - 0
src/main/java/com/zhili/dashboard/mapper/DeviceMapper.java

@@ -0,0 +1,16 @@
+package com.zhili.dashboard.mapper;
+
+import com.zhili.dashboard.entity.Device;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 设备信息 Mapper 接口
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+public interface DeviceMapper extends BaseMapper<Device> {
+
+}

+ 41 - 0
src/main/java/com/zhili/dashboard/mapper/DistributionMapMapper.java

@@ -0,0 +1,41 @@
+package com.zhili.dashboard.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhili.dashboard.entity.DistributionMap;
+import org.apache.ibatis.annotations.MapKey;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * 组织机构 Mapper 接口
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+public interface DistributionMapMapper extends BaseMapper<DistributionMap> {
+
+    /**
+     * 电池状态统计信息
+     *
+     * @param dateStr 参数
+     * @param hourStr 参数
+     * @return java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getDeviceStatusList(@Param("dateStr") String dateStr, @Param("hourStr") String hourStr,
+                                                  @Param("yesStr") String yesStr, @Param("yesHourStr") String yesHourStr);
+
+    /**
+     * 电池状态统计信息
+     *
+     * @param dateStr 参数
+     * @param hourStr 参数
+     * @return java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getOnLine(@Param("dateStr") String dateStr, @Param("hourStr") String hourStr);
+}

+ 34 - 0
src/main/java/com/zhili/dashboard/mapper/FaultMonthRateMapper.java

@@ -0,0 +1,34 @@
+package com.zhili.dashboard.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhili.dashboard.entity.FaultMonthRate;
+import org.apache.ibatis.annotations.MapKey;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * 组织机构 Mapper 接口
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+public interface FaultMonthRateMapper extends BaseMapper<FaultMonthRate> {
+    /**
+     * 某年安全事故率
+     * @param dateStr 参数
+     * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getFaultRate(@Param("dateStr") String dateStr);
+
+    /**
+     * 某年安全事故率
+     * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getFaultRateList();
+}

+ 14 - 0
src/main/java/com/zhili/dashboard/mapper/ModelMapper.java

@@ -0,0 +1,14 @@
+package com.zhili.dashboard.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhili.dashboard.entity.Model;
+
+/**
+ * 模型Mapper接口
+ *
+ * @author hz
+ * @date 2022-02-25
+ */
+public interface ModelMapper extends BaseMapper<Model> {
+
+}

+ 24 - 0
src/main/java/com/zhili/dashboard/mapper/OnlineMapper.java

@@ -0,0 +1,24 @@
+package com.zhili.dashboard.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhili.dashboard.entity.Online;
+import org.apache.ibatis.annotations.MapKey;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 模型Mapper接口
+ *
+ * @author hz
+ * @date 2022-02-25
+ */
+public interface OnlineMapper extends BaseMapper<Online> {
+
+    /**
+     * 在线电池统计
+     * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
+     */
+    @MapKey("id")
+    List<Map<String, Object>> getOnLine();
+}

+ 16 - 0
src/main/java/com/zhili/dashboard/mapper/OrgMapper.java

@@ -0,0 +1,16 @@
+package com.zhili.dashboard.mapper;
+
+import com.zhili.dashboard.entity.Org;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 组织机构 Mapper 接口
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+public interface OrgMapper extends BaseMapper<Org> {
+
+}

+ 16 - 0
src/main/java/com/zhili/dashboard/mapper/StatisticsMapper.java

@@ -0,0 +1,16 @@
+package com.zhili.dashboard.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhili.dashboard.entity.Statistics;
+
+/**
+ * <p>
+ * 电池数量&累计充放电总量统计 Mapper 接口
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+public interface StatisticsMapper extends BaseMapper<Statistics> {
+
+}

+ 288 - 0
src/main/java/com/zhili/dashboard/redis/RedisCache.java

@@ -0,0 +1,288 @@
+package com.zhili.dashboard.redis;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.BoundSetOperations;
+import org.springframework.data.redis.core.HashOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.data.redis.core.script.DefaultRedisScript;
+import org.springframework.data.redis.core.script.RedisScript;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * spring redis 工具类
+ *
+ * @author user
+ **/
+@SuppressWarnings(value = {"unchecked", "rawtypes"})
+@Component
+public class RedisCache {
+    @Autowired
+    public RedisTemplate redisTemplate;
+    private static final Long SUCCESS = 1L;
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key   缓存的键值
+     * @param value 缓存的值
+     */
+    public <T> void setCacheObject(final String key, final T value) {
+        redisTemplate.opsForValue().set(key, value);
+    }
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key      缓存的键值
+     * @param value    缓存的值
+     * @param timeout  时间
+     * @param timeUnit 时间颗粒度
+     */
+    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
+        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
+    }
+
+    /**
+     * 设置有效时间
+     *
+     * @param key     Redis键
+     * @param timeout 超时时间
+     * @return true=设置成功;false=设置失败
+     */
+    public boolean expire(final String key, final long timeout) {
+        return expire(key, timeout, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 设置有效时间
+     *
+     * @param key     Redis键
+     * @param timeout 超时时间
+     * @param unit    时间单位
+     * @return true=设置成功;false=设置失败
+     */
+    public boolean expire(final String key, final long timeout, final TimeUnit unit) {
+        return redisTemplate.expire(key, timeout, unit);
+    }
+
+    /**
+     * 获得缓存的基本对象。
+     *
+     * @param key 缓存键值
+     * @return 缓存键值对应的数据
+     */
+    public <T> T getCacheObject(final String key) {
+        ValueOperations<String, T> operation = redisTemplate.opsForValue();
+        return operation.get(key);
+    }
+
+    /**
+     * 删除单个对象
+     *
+     * @param key boolean
+     */
+    public boolean deleteObject(final String key) {
+        return redisTemplate.delete(key);
+    }
+
+    /**
+     * 删除集合对象
+     *
+     * @param collection 多个对象
+     * @return long
+     */
+    public long deleteObject(final Collection collection) {
+        return redisTemplate.delete(collection);
+    }
+
+    /**
+     * 缓存List数据
+     *
+     * @param key      缓存的键值
+     * @param dataList 待缓存的List数据
+     * @return 缓存的对象
+     */
+    public <T> long setCacheList(final String key, final List<T> dataList) {
+        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
+        return count == null ? 0 : count;
+    }
+
+    /**
+     * 取出列表数据
+     *
+     * @param key 键值
+     * @return 缓存的对象
+     */
+    public <T> Object lpopCacheList(final String key) {
+        Object obj = redisTemplate.opsForList().leftPop(key);
+        return obj;
+    }
+
+    /**
+     * 获得缓存的list对象
+     *
+     * @param key 缓存的键值
+     * @return 缓存键值对应的数据
+     */
+    public <T> List<T> getCacheList(final String key) {
+        return redisTemplate.opsForList().range(key, 0, -1);
+    }
+
+    /**
+     * 缓存Set
+     *
+     * @param key     缓存键值
+     * @param dataSet 缓存的数据
+     * @return 缓存数据的对象
+     */
+    public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet) {
+        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
+        Iterator<T> it = dataSet.iterator();
+        while (it.hasNext()) {
+            setOperation.add(it.next());
+        }
+        return setOperation;
+    }
+
+    /**
+     * 获得缓存的set
+     *
+     * @param key
+     * @return
+     */
+    public <T> Set<T> getCacheSet(final String key) {
+        return redisTemplate.opsForSet().members(key);
+    }
+
+    /**
+     * 缓存Map
+     *
+     * @param key
+     * @param dataMap
+     */
+    public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
+        if (dataMap != null) {
+            redisTemplate.opsForHash().putAll(key, dataMap);
+        }
+    }
+
+    /**
+     * 获得缓存的Map
+     *
+     * @param key
+     * @return
+     */
+    public <T> Map<String, T> getCacheMap(final String key) {
+        return redisTemplate.opsForHash().entries(key);
+    }
+
+    /**
+     * 往Hash中存入数据
+     *
+     * @param key   Redis键
+     * @param hKey  Hash键
+     * @param value 值
+     */
+    public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
+        redisTemplate.opsForHash().put(key, hKey, value);
+    }
+
+    /**
+     * 获取Hash中的数据
+     *
+     * @param key  Redis键
+     * @param hKey Hash键
+     * @return Hash中的对象
+     */
+    public <T> T getCacheMapValue(final String key, final String hKey) {
+        HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
+        return opsForHash.get(key, hKey);
+    }
+
+    /**
+     * 获取多个Hash中的数据
+     *
+     * @param key   Redis键
+     * @param hKeys Hash键集合
+     * @return Hash对象集合
+     */
+    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) {
+        return redisTemplate.opsForHash().multiGet(key, hKeys);
+    }
+
+    /**
+     * 获得缓存的基本对象列表
+     *
+     * @param pattern 字符串前缀
+     * @return 对象列表
+     */
+    public Collection<String> keys(final String pattern) {
+        return redisTemplate.keys(pattern);
+    }
+
+
+    /**
+     * 获取锁
+     *
+     * @param lockKey         参数
+     * @param value           参数
+     * @param expireTime:单位-秒
+     * @return boolean
+     */
+    public boolean getLock(String lockKey, Object value, int expireTime) {
+        try {
+            //log.info("添加分布式锁key={},expireTime={}",lockKey,expireTime);
+            String script = "if redis.call('setNx',KEYS[1],ARGV[1]) then if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('expire',KEYS[1],ARGV[2]) else return 0 end end";
+            RedisScript<String> redisScript = new DefaultRedisScript<>(script, String.class);
+            Object result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey), value, expireTime);
+            if (SUCCESS.equals(result)) {
+                return true;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return false;
+    }
+
+    /**
+     * 释放锁
+     *
+     * @param lockKey 参数
+     * @param value   参数
+     * @return boolean
+     */
+    public boolean releaseLock(String lockKey, String value) {
+        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
+        RedisScript<String> redisScript = new DefaultRedisScript<>(script, String.class);
+        Object result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey), value);
+        if (SUCCESS.equals(result)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key 缓存的键值
+     */
+    public <T> Boolean hasKey(final String key) {
+        return redisTemplate.hasKey(key);
+    }
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key 缓存的键值
+     */
+    public <T> long incr(final String key, final long index) {
+        Object cacheObject = getCacheObject(key);
+        long order = (long) cacheObject + index;
+        setCacheObject(key, order);
+        return order;
+    }
+}

+ 23 - 0
src/main/java/com/zhili/dashboard/req/MapParam.java

@@ -0,0 +1,23 @@
+package com.zhili.dashboard.req;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author zyg
+ * @className RadarParam
+ * @date 2022年07月07日 17:38
+ */
+@Data
+public class MapParam implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "省份,空值为全国")
+    private String province;
+
+    @ApiModelProperty(value = "类型,1-报警(默认) 2-预警")
+    private Integer type;
+}

+ 20 - 0
src/main/java/com/zhili/dashboard/req/ProvinceParam.java

@@ -0,0 +1,20 @@
+package com.zhili.dashboard.req;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author zyg
+ * @className ProvinceParam
+ * @date 2022年07月07日 17:38
+ */
+@Data
+public class ProvinceParam implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "省份,空值为全国")
+    private String province;
+}

+ 23 - 0
src/main/java/com/zhili/dashboard/req/RadarParam.java

@@ -0,0 +1,23 @@
+package com.zhili.dashboard.req;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author zyg
+ * @className RadarParam
+ * @date 2022年07月07日 17:38
+ */
+@Data
+public class RadarParam implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "id")
+    private Long id;
+
+    @ApiModelProperty(value = "电池编号")
+    private String sn;
+}

+ 42 - 0
src/main/java/com/zhili/dashboard/req/TableInfoParam.java

@@ -0,0 +1,42 @@
+package com.zhili.dashboard.req;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 对外mysql数据访问
+ *
+ * @author zyg
+ * @date 2022-05-30
+ */
+@Data
+public class TableInfoParam implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * id最小值
+     */
+    private String condition;
+
+    /**
+     * id最大值
+     */
+    private String fields;
+
+    /**
+     * 表名
+     */
+    private String tableName;
+
+    /**
+     * 数据源名称
+     */
+    private String interfaceName;
+
+    /**
+     * 用于数据外发
+     */
+    private String signature;
+}

+ 75 - 0
src/main/java/com/zhili/dashboard/scheduler/JobScheduler.java

@@ -0,0 +1,75 @@
+package com.zhili.dashboard.scheduler;
+
+import com.zhili.dashboard.service.IAlarmMsgService;
+import com.zhili.dashboard.service.IAlarmMsgWarnService;
+import com.zhili.dashboard.service.IDeviceDurationService;
+import com.zhili.dashboard.service.IDeviceService;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * @author user
+ */
+@Component
+public class JobScheduler {
+    @Resource
+    IDeviceService deviceService;
+    @Resource
+    IAlarmMsgService alarmMsgService;
+    @Resource
+    IAlarmMsgWarnService alarmMsgWarnService;
+    @Resource
+    IDeviceDurationService deviceDurationService;
+    /**
+     * 同步电池信息
+     * 10min一次
+     */
+    @Async
+    @Scheduled(cron = "0 */10 * * * ?")
+    public void syncBattery() {
+        deviceService.syncBattery();
+    }
+
+    /**
+     * 同步报警信息
+     * 10min一次
+     */
+    @Async
+    //@Scheduled(cron = "0 */2 * * * ?")
+    public void syncAlarmMsg() {
+        alarmMsgService.syncAlarmMsg();
+    }
+
+    /**
+     * 同步预警信息
+     * 2min一次
+     */
+    @Async
+    //@Scheduled(cron = "0 */2 * * * ?")
+    public void syncAlarmMsgWarnIng() {
+        alarmMsgWarnService.syncAlarmMsg();
+    }
+
+    /**
+     * 更新故障状态
+     * 1小时一次
+     */
+    @Async
+    @Scheduled(cron = "0 0 */1 * * ?")
+    public void syncAlarmMsgStatus() {
+        alarmMsgService.syncAlarmMsgStatus();
+    }
+
+    /**
+     * 同步析锂时长信息
+     * 1小时一次
+     */
+    @Async
+    @Scheduled(cron = "0 0 */1 * * ?")
+    public void syncDuration() {
+        deviceDurationService.syncDuration();
+    }
+}

+ 172 - 0
src/main/java/com/zhili/dashboard/service/IAlarmMsgService.java

@@ -0,0 +1,172 @@
+package com.zhili.dashboard.service;
+
+import com.zhili.dashboard.base.*;
+import com.zhili.dashboard.entity.AlarmMsg;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhili.dashboard.entity.CmdDetail;
+import com.zhili.dashboard.req.MapParam;
+import com.zhili.dashboard.req.ProvinceParam;
+import com.zhili.dashboard.req.RadarParam;
+import com.zhili.dashboard.vo.*;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * <p>
+ * 云控信息表 服务类
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+public interface IAlarmMsgService extends IService<AlarmMsg> {
+    /**
+     * 同步电池信息
+     */
+    void syncAlarmMsg();
+
+    /**
+     * 更新故障信息
+     */
+    void syncAlarmMsgStatus();
+
+    /**
+     * 故障级别饼图
+     *
+     * @param type 参数
+     * @return java.util.List<com.zhili.dashboard.base.BaseCycleChartVo>
+     */
+    List<BaseCycleChartVo> getAlarmLevelPie(Integer type);
+
+    /**
+     * 故障预警历史信息-24小时
+     *
+     * @return com.zhili.dashboard.base.BaseLineDecimalVo
+     */
+    BaseLineDecimalVo getAlarmHistoryLineForDay();
+
+    /**
+     * 故障预警历史信息-30天
+     *
+     * @return com.zhili.dashboard.base.BaseLineDecimalVo
+     */
+    BaseLineDecimalVo getAlarmHistoryLineForMonth();
+
+    /**
+     * 高危用户列表
+     *
+     * @return List<HighRiskVo>
+     */
+    List<HighRiskVo> getHighRisk();
+
+    /**
+     * 风险等级电池统计信息
+     *
+     * @return java.util.List<com.zhili.dashboard.vo.RiskListVo>
+     */
+    List<RiskListVo> getRiskList();
+
+    /**
+     * 故障电池与正常电池统计信息
+     *
+     * @return java.util.List<BaseCycleChartVo>
+     */
+    List<BaseCycleChartVo> getFaultList();
+
+    /**
+     * 在线电池统计信息
+     *
+     * @return java.util.List<com.zhili.dashboard.base.BaseCycleChartVo>
+     */
+    OnLineVo getOnLine();
+
+    /**
+     * 电池状态统计信息
+     *
+     * @return BaseLineDecimalVo
+     */
+    BaseLineDecimalVo getDeviceStatusList();
+
+    /**
+     * 区域电池信息排名(仅北京市)
+     * @param param 参数
+     * @return java.util.List<com.zhili.dashboard.vo.SceneGroupVo>
+     */
+    List<SceneGroupVo> getDistrictOrder(ProvinceParam param);
+
+    /**
+     * 应用场景电池信息
+     *
+     * @param param 参数
+     * @return java.util.List<com.zhili.dashboard.vo.SceneGroupVo>
+     */
+    List<SceneGroupVo> getSceneGroup(ProvinceParam param);
+
+    /**
+     * 累计安全拦截次数&安全运行时长
+     *
+     * @return SafeguardVo
+     */
+    SafeguardVo getSafeguard();
+
+    /**
+     * 累计信息统计
+     *
+     * @return com.zhili.dashboard.vo.CumulativeInfoVo
+     */
+    CumulativeInfoVo getCumulativeInfo();
+
+    /**
+     * 累计循环次数
+     * @return java.lang.Long
+     */
+    Long getCumulativeCycle();
+
+    /**
+     * 电池详情
+     * @param id 参数
+     * @return AlarmDetailVo
+     */
+    AlarmDetailVo getDetail(Long id);
+
+    /**
+     * 雷达图
+     * @param param 参数
+     * @return KindValueListVo
+     */
+    KindValueDoubleListVo getRadar(RadarParam param);
+
+    /**
+     * 地图信息
+     * @param param 参数
+     * @return java.util.List<BatteryMapVo>
+     */
+    List<BatteryMapVo> getBatteryMap(MapParam param);
+
+    /**
+     * 安全事故率
+     * @param param 参数
+     * @return java.math.BigDecimal
+     */
+    BigDecimal getFaultRate(MapParam param);
+
+    /**
+     * 安全事故率
+     * @param param 参数
+     * @return BaseLineDecimalVo
+     */
+    BaseLineDecimalVo getFaultRateList(MapParam param);
+
+    /**
+     * 安全明细
+     * @return java.util.List<CmdDetail>
+     */
+    List<CmdDetail> getCmdDetailList();
+
+    /**
+     * 安全概览
+     * @return java.util.List<BaseCycleChartVo>
+     */
+    List<BaseCycleChartVo> getCmdOverview();
+}

+ 19 - 0
src/main/java/com/zhili/dashboard/service/IAlarmMsgWarnService.java

@@ -0,0 +1,19 @@
+package com.zhili.dashboard.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhili.dashboard.entity.AlarmMsgWarn;
+
+/**
+ * <p>
+ * 云控信息表 服务类
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+public interface IAlarmMsgWarnService extends IService<AlarmMsgWarn> {
+    /**
+     * 同步电池信息
+     */
+    void syncAlarmMsg();
+}

+ 16 - 0
src/main/java/com/zhili/dashboard/service/ICommandService.java

@@ -0,0 +1,16 @@
+package com.zhili.dashboard.service;
+
+import com.zhili.dashboard.entity.Command;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 电池命令下发数据 服务类
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+public interface ICommandService extends IService<Command> {
+
+}

+ 19 - 0
src/main/java/com/zhili/dashboard/service/IDeviceDurationService.java

@@ -0,0 +1,19 @@
+package com.zhili.dashboard.service;
+
+import com.zhili.dashboard.entity.DeviceDuration;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 电池状态统计信息 服务类
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+public interface IDeviceDurationService extends IService<DeviceDuration> {
+    /**
+     * 同步统计信息
+     */
+    void syncDuration();
+}

+ 20 - 0
src/main/java/com/zhili/dashboard/service/IDeviceService.java

@@ -0,0 +1,20 @@
+package com.zhili.dashboard.service;
+
+import com.zhili.dashboard.entity.Device;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 设备信息 服务类
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+public interface IDeviceService extends IService<Device> {
+
+    /**
+     * 同步电池信息
+     */
+    void syncBattery();
+}

+ 16 - 0
src/main/java/com/zhili/dashboard/service/IOrgService.java

@@ -0,0 +1,16 @@
+package com.zhili.dashboard.service;
+
+import com.zhili.dashboard.entity.Org;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 组织机构 服务类
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+public interface IOrgService extends IService<Org> {
+
+}

+ 16 - 0
src/main/java/com/zhili/dashboard/service/IStatisticsService.java

@@ -0,0 +1,16 @@
+package com.zhili.dashboard.service;
+
+import com.zhili.dashboard.entity.Statistics;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 电池数量&累计充放电总量统计 服务类
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+public interface IStatisticsService extends IService<Statistics> {
+
+}

+ 244 - 0
src/main/java/com/zhili/dashboard/service/TokenService.java

@@ -0,0 +1,244 @@
+//package com.service;
+//
+//import com.alibaba.fastjson.JSON;
+//import com.base.Constants;
+//import com.base.HzTokenResponse;
+//import com.base.LoginUser;
+//import com.redis.RedisCache;
+//import com.utils.*;
+//import eu.bitwalker.useragentutils.UserAgent;
+//import io.jsonwebtoken.Claims;
+//import io.jsonwebtoken.Jwts;
+//import io.jsonwebtoken.SignatureAlgorithm;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.beans.factory.annotation.Value;
+//import org.springframework.stereotype.Component;
+//
+//import javax.servlet.http.HttpServletRequest;
+//import java.util.HashMap;
+//import java.util.Map;
+//import java.util.UUID;
+//import java.util.concurrent.TimeUnit;
+//
+///**
+// * token验证处理
+// *
+// * @author user
+// */
+//@Component
+//public class TokenService {
+//    // 令牌自定义标识
+//    @Value("${token.header}")
+//    private String header;
+//
+//    // 令牌秘钥
+//    @Value("${token.secret}")
+//    private String secret;
+//
+//    // 令牌有效期(默认30分钟)
+//    @Value("${token.expireTime}")
+//    private int expireTime;
+//
+//    protected static final long MILLIS_SECOND = 1000;
+//
+//    protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
+//
+//    private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
+//
+//
+//    @Value("${hz.checkToken}")
+//    private String checkToken;
+//    @Value("${hz.refreshToken}")
+//    private String refreshToken;
+//    @Value("${hz.getUsers}")
+//    private String getUsers;
+//
+//    @Autowired
+//    private RedisCache redisCache;
+//
+//
+//    private Boolean checkAccessToken(Long userId) {
+//        String accessToken = redisCache.getCacheObject(userId + "-token");
+//        if (StringUtils.isNotEmpty(accessToken)) {
+//            String param = "accessToken=" + accessToken;
+//            String response = HttpUtils.sendGet(checkToken, param, "UTF-8");
+//            HzTokenResponse hzTokenResponse = JSON.parseObject(response, HzTokenResponse.class);
+//            return hzTokenResponse.getCode() == 20000
+//                    && hzTokenResponse.getData() != null
+//                    && Long.toString(userId).equals(hzTokenResponse.getData());
+//        }
+//        return false;
+//    }
+//
+//    /**
+//     * 获取用户身份信息
+//     *
+//     * @return 用户信息
+//     */
+//    public LoginUser getLoginUser(HttpServletRequest request) {
+//
+//        // 获取请求携带的令牌
+//        String token = getToken(request);
+//        if (StringUtils.isNotEmpty(token)) {
+//            try {
+//                Claims claims = parseToken(token);
+//                // 解析对应的权限以及用户信息
+//                String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
+//                String userKey = getTokenKey(uuid);
+//                LoginUser user = redisCache.getCacheObject(userKey);
+//                if (user != null && !user.getUsername().equals("admin")) {
+//                    boolean bToken = checkAccessToken(user.getId());
+//                    if (bToken) {
+//                        return user;
+//                    }
+//                }
+//                return user;
+//            } catch (Exception e) {
+//            }
+//        }
+//        return null;
+//    }
+//
+//    /**
+//     * 设置用户身份信息
+//     */
+//    public void setLoginUser(LoginUser loginUser) {
+//        if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) {
+//            refreshToken(loginUser);
+//        }
+//    }
+//
+//    /**
+//     * 删除用户身份信息
+//     */
+//    public void delLoginUser(String token) {
+//        if (StringUtils.isNotEmpty(token)) {
+//            String userKey = getTokenKey(token);
+//            redisCache.deleteObject(userKey);
+//        }
+//    }
+//
+//    /**
+//     * 删除用户身份信息
+//     */
+//    public void delParentToken(Long userId) {
+//        if (userId != null) {
+//            String userKey = getTokenKey(userId + "-token");
+//            redisCache.deleteObject(userKey);
+//        }
+//    }
+//
+//    /**
+//     * 创建令牌
+//     *
+//     * @param loginUser 用户信息
+//     * @return 令牌
+//     */
+//    public String createToken(LoginUser loginUser) {
+//        String token = UUID.randomUUID().toString();
+//        loginUser.setToken(token);
+//        setUserAgent(loginUser);
+//        refreshToken(loginUser);
+//
+//        Map<String, Object> claims = new HashMap<>();
+//        claims.put(Constants.LOGIN_USER_KEY, token);
+////        claims.put("accessToken", accessToken);
+//        return createToken(claims);
+//    }
+//
+//    /**
+//     * 验证令牌有效期,相差不足20分钟,自动刷新缓存
+//     *
+//     * @param loginUser
+//     * @return 令牌
+//     */
+//    public void verifyToken(LoginUser loginUser) {
+//        long expireTime = loginUser.getExpireTime();
+//        long currentTime = System.currentTimeMillis();
+//        if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
+//            refreshToken(loginUser);
+//        }
+//    }
+//
+//    /**
+//     * 刷新令牌有效期
+//     *
+//     * @param loginUser 登录信息
+//     */
+//    public void refreshToken(LoginUser loginUser) {
+//        loginUser.setLoginTime(System.currentTimeMillis());
+//        loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
+//        // 根据uuid将loginUser缓存
+//        String userKey = getTokenKey(loginUser.getToken());
+//        redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
+//    }
+//
+//    /**
+//     * 设置用户代理信息
+//     *
+//     * @param loginUser 登录信息
+//     */
+//    public void setUserAgent(LoginUser loginUser) {
+//        UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
+//        String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
+//        loginUser.setIpaddr(ip);
+//        loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
+//        loginUser.setBrowser(userAgent.getBrowser().getName());
+//        loginUser.setOs(userAgent.getOperatingSystem().getName());
+//    }
+//
+//    /**
+//     * 从数据声明生成令牌
+//     *
+//     * @param claims 数据声明
+//     * @return 令牌
+//     */
+//    private String createToken(Map<String, Object> claims) {
+//        String token = Jwts.builder()
+//                .setClaims(claims)
+//                .signWith(SignatureAlgorithm.HS512, secret).compact();
+//        return token;
+//    }
+//
+//    /**
+//     * 从令牌中获取数据声明
+//     *
+//     * @param token 令牌
+//     * @return 数据声明
+//     */
+//    private Claims parseToken(String token) {
+//        return Jwts.parser()
+//                .setSigningKey(secret)
+//                .parseClaimsJws(token)
+//                .getBody();
+//    }
+//
+//    /**
+//     * 从令牌中获取用户名
+//     *
+//     * @param token 令牌
+//     * @return 用户名
+//     */
+//    public String getUsernameFromToken(String token) {
+//        Claims claims = parseToken(token);
+//        return claims.getSubject();
+//    }
+//
+//    /**
+//     * 获取请求token
+//     *
+//     * @param request
+//     * @return token
+//     */
+//    private String getToken(HttpServletRequest request) {
+//        String token = request.getHeader(header);
+//        if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) {
+//            token = token.replace(Constants.TOKEN_PREFIX, "");
+//        }
+//        return token;
+//    }
+//
+//    private String getTokenKey(String uuid) {
+//        return Constants.LOGIN_TOKEN_KEY + uuid;
+//    }
+//}

+ 1559 - 0
src/main/java/com/zhili/dashboard/service/impl/AlarmMsgServiceImpl.java

@@ -0,0 +1,1559 @@
+package com.zhili.dashboard.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.zhili.dashboard.base.*;
+import com.zhili.dashboard.entity.*;
+import com.zhili.dashboard.enums.*;
+import com.zhili.dashboard.mapper.*;
+import com.zhili.dashboard.req.MapParam;
+import com.zhili.dashboard.req.ProvinceParam;
+import com.zhili.dashboard.req.RadarParam;
+import com.zhili.dashboard.req.TableInfoParam;
+import com.zhili.dashboard.utils.OkHttpCli;
+import com.zhili.dashboard.utils.StringUtils;
+import com.zhili.dashboard.vo.*;
+import com.zhili.dashboard.service.IAlarmMsgService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhili.dashboard.utils.DateUtil;
+import com.zhili.dashboard.utils.LineTimeChartVo;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.AsyncResult;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.*;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 云控信息表 服务实现类
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Service
+public class AlarmMsgServiceImpl extends ServiceImpl<AlarmMsgMapper, AlarmMsg> implements IAlarmMsgService {
+    @Resource
+    OkHttpCli okHttpCli;
+    @Resource
+    AlarmMsgMapper alarmMsgMapper;
+    @Resource
+    DeviceMapper deviceMapper;
+    @Resource
+    DistributionMapMapper distributionMapMapper;
+    @Resource
+    DeviceDurationMapper deviceDurationMapper;
+    @Resource
+    ModelMapper modelMapper;
+    @Resource
+    FaultMonthRateMapper faultMonthRateMapper;
+    @Resource
+    AlarmMsgWarnMapper alarmMsgWarnMapper;
+    @Resource
+    CmdDetailMapper cmdDetailMapper;
+
+    /**
+     * 数据获取地址
+     */
+    private static final String BATTERY_URL = "/admin/v1/hzBattery";
+    /**
+     * 故障信息地址
+     */
+    private static final String SIGNATURE = "AD5C4EC001352FFAC3A03CBA787A7417";
+
+    @Value("${openapi.token-secret}")
+    private String tokenSecret;
+    @Value("${openapi.url}")
+    private String openApiUrl;
+
+    private final String[] hours = {"0", "1", "2", "3", "4", "5", "6", "7",
+            "8", "9", "10", "11", "12", "13", "14", "15", "16",
+            "17", "18", "19", "20", "21", "22", "23"};
+
+    /**
+     * 故障级别饼图
+     *
+     * @param type 参数
+     * @return java.util.List<com.zhili.dashboard.base.BaseCycleChartVo>
+     */
+    @Override
+    public List<BaseCycleChartVo> getAlarmLevelPie(Integer type) {
+        List<BaseCycleChartVo> voList = new ArrayList<>();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 23:59:59");
+        String dateStr = sdf.format(System.currentTimeMillis() - 24 * 60 * 60 * 1000);
+        switch (type) {
+            case 2:
+                dateStr = DateUtil.getPreviousWeekSunday() + " 23:59:59";
+                break;
+            case 3:
+                dateStr = DateUtil.getLastMaxMonthDate() + " 23:59:59";
+                break;
+            default:
+        }
+        List<AlarmMsg> alarmMsgList = alarmMsgMapper.getAlarmLevelPie(dateStr);
+        long total = alarmMsgList.stream().mapToLong(AlarmMsg::getQuantity).sum();
+        //计算比例
+        AlarmLevelEnum[] enums = AlarmLevelEnum.values();
+        for (AlarmLevelEnum en : enums) {
+            BaseCycleChartVo v = new BaseCycleChartVo();
+            v.setName(en.message());
+            v.setLevelIcon("l" + en.code() + "ico");
+            v.setCount(0L);
+            for (AlarmMsg o : alarmMsgList) {
+                if (en.code().equals(o.getFaultLevel())) {
+                    v.setCount(o.getQuantity());
+                    break;
+                }
+            }
+            if (total == 0) {
+                v.setPercent(BigDecimal.ZERO);
+            } else {
+                v.setPercent(BigDecimal.valueOf(v.getCount() * 100).divide(BigDecimal.valueOf(total), 2, RoundingMode.HALF_UP));
+            }
+            voList.add(v);
+        }
+        return voList;
+    }
+
+    /**
+     * 故障预警历史信息-24小时
+     *
+     * @return com.zhili.dashboard.base.BaseIntegerLineChartVo
+     */
+    @Override
+    public BaseLineDecimalVo getAlarmHistoryLineForDay() {
+        BaseLineDecimalVo vo = new BaseLineDecimalVo();
+        //横轴数据填充
+        List<String> timeAxisList = Arrays.asList(hours);
+        vo.setTimeAxis(timeAxisList);
+
+        //曲线图数据填充
+        List<KindValueDoubleListVo> kindList = new ArrayList<>();
+        //数据查询
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        long currentTime = System.currentTimeMillis();
+
+        //按照小时进行统计
+        KindValueDoubleListVo v = new KindValueDoubleListVo();
+        v.setName("24小时故障预警历史信息");
+        List<BigDecimal> valueList = new ArrayList<>();
+        timeAxisList.forEach(m -> {
+            valueList.add(BigDecimal.ZERO);
+        });
+        v.setValue(valueList);
+        kindList.add(v);
+        KindValueDoubleListVo v1 = new KindValueDoubleListVo();
+        v1.setName("24小时故障完结率");
+        List<BigDecimal> valueList1 = new ArrayList<>();
+        timeAxisList.forEach(m -> {
+            valueList1.add(BigDecimal.ZERO);
+        });
+        v1.setValue(valueList1);
+        kindList.add(v1);
+
+        List<Map<String, Object>> mapList = alarmMsgMapper.getAlarmHistoryDay(sdf.format(currentTime - 24 * 60 * 60 * 1000));
+        if (mapList.size() > 0) {
+            List<LineChartVo> lineChartVoList = JSONArray.parseArray(JSON.toJSONString(mapList), LineChartVo.class);
+            for (int i = 0; i < timeAxisList.size(); i++) {
+                if (lineChartVoList.size() > 0) {
+                    int finalI = i;
+                    lineChartVoList.forEach(o -> {
+                        if (o.getNum().equals(finalI)) {
+                            List<BigDecimal> tempList = new ArrayList<>(kindList.get(0).getValue());
+                            tempList.set(finalI, BigDecimal.valueOf(o.getQuantity()));
+                            kindList.get(0).setValue(tempList);
+                        }
+                    });
+                }
+            }
+        }
+
+        //故障完结率
+        List<Map<String, Object>> mapList1 = alarmMsgMapper.getAlarmHistoryDayOverRate(sdf.format(currentTime - 24 * 60 * 60 * 1000));
+        if (mapList1.size() > 0) {
+            List<LineChartVo> lineChartVoList = JSONArray.parseArray(JSON.toJSONString(mapList1), LineChartVo.class);
+            for (int i = 0; i < timeAxisList.size(); i++) {
+                if (lineChartVoList.size() > 0) {
+                    int finalI = i;
+                    lineChartVoList.forEach(o -> {
+                        if (o.getNum().equals(finalI)) {
+                            List<BigDecimal> tempList = new ArrayList<>(kindList.get(1).getValue());
+                            BigDecimal rate = kindList.get(0).getValue().get(finalI).compareTo(BigDecimal.ZERO) > 0
+                                    ? BigDecimal.valueOf(o.getQuantity() * 100).divide(kindList.get(0).getValue().get(finalI), 2, RoundingMode.HALF_UP)
+                                    : BigDecimal.ZERO;
+                            tempList.set(finalI, rate);
+                            kindList.get(1).setValue(tempList);
+                        }
+                    });
+                }
+            }
+        }
+
+        vo.setKindList(kindList);
+        return vo;
+    }
+
+    /**
+     * 故障预警历史信息-30天
+     *
+     * @return com.zhili.dashboard.base.BaseLineDecimalVo
+     */
+    @Override
+    public BaseLineDecimalVo getAlarmHistoryLineForMonth() {
+        BaseLineDecimalVo vo = new BaseLineDecimalVo();
+
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
+        Date endTime = new Date();
+        Date startTime = new Date(endTime.getTime() - 29L * 24 * 60 * 60 * 1000);
+        //横轴数据填充
+        List<String> timeAxisList = splitDateList(startTime, endTime);
+        vo.setTimeAxis(timeAxisList);
+
+        //曲线图数据填充
+        List<KindValueDoubleListVo> kindList = new ArrayList<>();
+
+        //按照小时进行统计
+        KindValueDoubleListVo v = new KindValueDoubleListVo();
+        v.setName("30天故障预警历史信息");
+        List<BigDecimal> valueList = new ArrayList<>();
+        timeAxisList.forEach(m -> {
+            valueList.add(BigDecimal.ZERO);
+        });
+        v.setValue(valueList);
+        kindList.add(v);
+        KindValueDoubleListVo v1 = new KindValueDoubleListVo();
+        v1.setName("30天故障完结率");
+        List<BigDecimal> valueList1 = new ArrayList<>();
+        timeAxisList.forEach(m -> {
+            valueList1.add(BigDecimal.ZERO);
+        });
+        v1.setValue(valueList1);
+        kindList.add(v1);
+
+        //数据查询
+        List<Map<String, Object>> mapList = alarmMsgMapper.getAlarmHistoryMonth(sdf.format(startTime));
+        if (mapList.size() > 0) {
+            List<LineTimeChartVo> lineChartVoList = JSONArray.parseArray(JSON.toJSONString(mapList), LineTimeChartVo.class);
+            for (int i = 0; i < timeAxisList.size(); i++) {
+                if (lineChartVoList.size() > 0) {
+                    for (LineTimeChartVo o : lineChartVoList) {
+                        if (o.getItem().equals(timeAxisList.get(i))) {
+                            List<BigDecimal> tempList = new ArrayList<>(kindList.get(0).getValue());
+                            tempList.set(i, BigDecimal.valueOf(o.getQuantity()));
+                            kindList.get(0).setValue(tempList);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        //故障完结率
+        List<Map<String, Object>> mapList1 = alarmMsgMapper.getAlarmHistoryOveMonthRate(sdf.format(startTime));
+        if (mapList1.size() > 0) {
+            List<LineTimeChartVo> lineChartVoList = JSONArray.parseArray(JSON.toJSONString(mapList1), LineTimeChartVo.class);
+            for (int i = 0; i < timeAxisList.size(); i++) {
+                if (lineChartVoList.size() > 0) {
+                    for (LineTimeChartVo o : lineChartVoList) {
+                        if (o.getItem().equals(timeAxisList.get(i))) {
+                            List<BigDecimal> tempList = new ArrayList<>(kindList.get(1).getValue());
+                            BigDecimal rate = kindList.get(0).getValue().get(i).compareTo(BigDecimal.ZERO) > 0
+                                    ? BigDecimal.valueOf(o.getQuantity() * 100).divide(kindList.get(0).getValue().get(i), 2, RoundingMode.HALF_UP)
+                                    : BigDecimal.ZERO;
+                            tempList.set(i, rate);
+                            kindList.get(1).setValue(tempList);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        for (int i = 0; i < kindList.get(0).getValue().size(); i++) {
+            List<BigDecimal> tempList = new ArrayList<>(kindList.get(0).getValue());
+            tempList.set(i, kindList.get(0).getValue().get(i).divide(BigDecimal.valueOf(1000), 0, RoundingMode.HALF_UP));
+            kindList.get(0).setValue(tempList);
+        }
+
+        vo.setKindList(kindList);
+        return vo;
+    }
+
+    /**
+     * 获取两个日期之间的所有日期集合
+     *
+     * @param startDate 开始日期
+     * @param endDate   截止日期
+     * @return java.util.List<java.lang.String>
+     */
+    private static List<String> splitDateList(Date startDate, Date endDate) {
+        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
+        List<String> listDate = new ArrayList<>();
+        try {
+            Calendar calendar = Calendar.getInstance();
+            calendar.setTime(startDate);
+            while (calendar.getTime().before(endDate) || calendar.getTime().equals(endDate)) {
+                listDate.add(df.format(calendar.getTime()));
+                calendar.add(Calendar.DAY_OF_MONTH, 1);
+            }
+            return listDate;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return listDate;
+    }
+
+    /**
+     * 高危用户列表
+     *
+     * @return List<HighRiskVo>
+     */
+    @Override
+    public List<HighRiskVo> getHighRisk() {
+        List<HighRiskVo> voList = new ArrayList<>();
+        //数据查询
+        List<Map<String, Object>> mapList = alarmMsgWarnMapper.getHighRisk();
+        if (!CollectionUtils.isEmpty(mapList)) {
+            voList = JSONArray.parseArray(JSON.toJSONString(mapList), HighRiskVo.class);
+            voList.forEach(o -> {
+                o.setSceneText(o.getScene() == null ? "未定义设备" : SceneEnum.getDesc(o.getScene()));
+                o.setSimpleSn(o.getSn().substring(7));
+                o.setBatteryCoreTypeText(o.getBatteryCoreType() == null ? "" : AlarmCoreTypeEnum.getDesc(o.getBatteryCoreType()));
+                o.setFaultStatusText(o.getFaultStatus() == null ? "" : AlarmFaultStatusEnum.getDesc(o.getFaultStatus()));
+                o.setUpdateBy(StringUtils.noPassByName(o.getUpdateBy()));
+                o.setOrgName(o.getUpdateBy());
+            });
+        }
+        return voList;
+    }
+
+    /**
+     * 风险等级电池统计信息
+     *
+     * @return java.util.List<com.zhili.dashboard.vo.RiskListVo>
+     */
+    @Override
+    public List<RiskListVo> getRiskList() {
+        List<RiskListVo> voList = new ArrayList<>();
+        for (AlarmLevelGroupEnum en : AlarmLevelGroupEnum.values()) {
+            RiskListVo v = new RiskListVo();
+            v.setItem(String.valueOf(en.code()));
+            v.setQuantity(0L);
+            voList.add(v);
+        }
+
+        //数据查询
+        List<Map<String, Object>> mapList = alarmMsgWarnMapper.getAlarmLevelGroup();
+        if (!CollectionUtils.isEmpty(mapList)) {
+            List<RiskListVo> list = JSONArray.parseArray(JSON.toJSONString(mapList), RiskListVo.class);
+            if (list.size() > 0) {
+                list = list.stream().sorted(Comparator.comparing(o -> Integer.parseInt(o.getItem())))
+                        .collect(Collectors.toList());
+                List<RiskListVo> finalList = list;
+                voList.forEach(o -> {
+                    finalList.forEach(m -> {
+                        if (m.getItem().equals(o.getItem())) {
+                            o.setQuantity(m.getQuantity());
+                        }
+                    });
+                    o.setItem(AlarmLevelGroupEnum.getDesc(Integer.parseInt(o.getItem())));
+                });
+            }
+        }
+        return voList;
+    }
+
+    /**
+     * 故障电池与正常电池统计信息
+     *
+     * @return java.util.List<com.zhili.dashboard.vo.RiskListVo>
+     */
+    @Override
+    public List<BaseCycleChartVo> getFaultList() {
+        List<BaseCycleChartVo> voList = new ArrayList<>();
+        //数据查询
+        long total = deviceMapper.selectCount(new QueryWrapper<Device>().select("distinct sn").eq("is_delete", 0));
+        long fault = alarmMsgMapper.selectCount(new QueryWrapper<AlarmMsg>()
+                .select("distinct sn")
+                .eq("fault_status", 0)
+                .eq("is_delete", 0));
+
+        BaseCycleChartVo vo = new BaseCycleChartVo();
+        vo.setName("故障电池");
+        vo.setCount(fault);
+        vo.setPercent(BigDecimal.valueOf(vo.getCount() * 100).divide(BigDecimal.valueOf(total), 2, RoundingMode.HALF_UP));
+        voList.add(vo);
+
+        BaseCycleChartVo va = new BaseCycleChartVo();
+        va.setName("正常电池");
+        va.setCount(total - fault);
+        va.setPercent(BigDecimal.valueOf(vo.getCount() * 100).divide(BigDecimal.valueOf(total), 2, RoundingMode.HALF_UP));
+        voList.add(va);
+
+        return voList;
+    }
+
+    /**
+     * 在线电池统计信息
+     *
+     * @return java.util.List<com.zhili.dashboard.base.BaseCycleChartVo>
+     */
+    @Override
+    public OnLineVo getOnLine() {
+        OnLineVo vo = new OnLineVo();
+        List<RiskListVo> list = new ArrayList<>();
+        //每时的总和
+        long total = deviceMapper.selectCount(new QueryWrapper<>());
+        vo.setTotal(total);
+        //数据查询
+        SimpleDateFormat sf = new SimpleDateFormat("yyyyMMdd");
+        SimpleDateFormat sfh = new SimpleDateFormat("HH");
+        long currentTime = System.currentTimeMillis() - 7 * 24 * 60 * 60 * 1000;
+        String dateStr = sf.format(currentTime);
+        String hourStr = sfh.format(currentTime);
+
+
+        List<Map<String, Object>> mapList = distributionMapMapper.getOnLine(dateStr, hourStr);
+        if (!CollectionUtils.isEmpty(mapList)) {
+            long count = (long) Math.abs(Double.parseDouble(mapList.get(0).get("total").toString()));
+            count = count + getSleepCount(Integer.parseInt(hourStr), -100).longValue();
+            vo.setCount(count);
+        }
+/*        List<Map<String, Object>> mapList = alarmMsgMapper.getOnLine();
+        if (!CollectionUtils.isEmpty(mapList)) {
+            list = JSONArray.parseArray(JSON.toJSONString(mapList), RiskListVo.class);
+            if (list.size() > 0) {
+                long total = list.stream().mapToLong(RiskListVo::getQuantity).sum();
+                vo.setTotal(total);
+                list.forEach(o -> {
+                    if ("1".equals(o.getItem())) {
+                        vo.setCount(o.getQuantity());
+                    }
+                });
+            }
+        }*/
+        return vo;
+    }
+
+    /**
+     * 电池状态统计信息
+     *
+     * @return BaseLineDecimalVo
+     */
+    @Override
+    public BaseLineDecimalVo getDeviceStatusList() {
+        BaseLineDecimalVo vo = new BaseLineDecimalVo();
+
+        SimpleDateFormat sf = new SimpleDateFormat("yyyyMMdd");
+        SimpleDateFormat sfh = new SimpleDateFormat("HH");
+        long currentTime = System.currentTimeMillis() - 7 * 24 * 60 * 60 * 1000;
+        long yesTime = System.currentTimeMillis() - 8 * 24 * 60 * 60 * 1000;
+        String dateStr = sf.format(currentTime);
+        String yesStr = sf.format(yesTime);
+        String hourStr = sfh.format(currentTime);
+        String yesHourStr = String.format("%2d", Integer.parseInt(hourStr) + 1);
+
+        List<String> timeAxisList = new ArrayList<>();
+        //横轴数据填充
+        List<String> timeOrderList = Arrays.asList(hours);
+        timeOrderList.forEach(o -> {
+            if (Integer.parseInt(hourStr) <= Integer.parseInt(o)) {
+                timeAxisList.add(o);
+            }
+        });
+        timeOrderList.forEach(o -> {
+            if (!timeAxisList.contains(o)) {
+                timeAxisList.add(o);
+            }
+        });
+        vo.setTimeAxis(timeAxisList);
+
+        List<KindValueDoubleListVo> kindList = new ArrayList<>();
+        DeviceStatusEnum[] enums = DeviceStatusEnum.values();
+        for (DeviceStatusEnum en : enums) {
+            KindValueDoubleListVo v = new KindValueDoubleListVo();
+            v.setName(String.valueOf(en.code()));
+            List<BigDecimal> valueList = new ArrayList<>();
+            timeAxisList.forEach(m -> {
+                valueList.add(BigDecimal.ZERO);
+            });
+            v.setValue(valueList);
+            kindList.add(v);
+        }
+
+        //数据查询
+        List<Map<String, Object>> mapList = distributionMapMapper.getDeviceStatusList(dateStr, hourStr, yesStr, yesHourStr);
+        if (!CollectionUtils.isEmpty(mapList)) {
+            List<DeviceStatusVo> list = JSONArray.parseArray(JSON.toJSONString(mapList), DeviceStatusVo.class);
+            if (list.size() > 0) {
+                //填充list
+                for (DeviceStatusEnum en : enums) {
+                    for (int i = 0; i < timeAxisList.size(); i++) {
+                        if (en.code().equals(DeviceStatusEnum.SLEEP.code())) {
+                            List<BigDecimal> tempList = new ArrayList<>(kindList.get(en.code() - 1).getValue());
+                            tempList.set(i, getSleepCount(Integer.parseInt(timeAxisList.get(i)), Integer.parseInt(hourStr)));
+                            kindList.get(en.code() - 1).setValue(tempList);
+                        } else {
+                            for (DeviceStatusVo m : list) {
+                                if (en.code().equals(Integer.parseInt(m.getItem()) + 1) && m.getNum().equals(Integer.parseInt(timeAxisList.get(i)))) {
+                                    List<BigDecimal> tempList = new ArrayList<>(kindList.get(en.code() - 1).getValue());
+                                    tempList.set(i, BigDecimal.valueOf(m.getQuantity()));
+                                    kindList.get(en.code() - 1).setValue(tempList);
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+
+            }
+        }
+        //每时的总和
+        long total = deviceMapper.selectCount(new QueryWrapper<>());
+        //离线数据 = 总 - 充 - 放 - 停
+        List<BigDecimal> totalList = new ArrayList<>();
+        for (int i = 0; i < timeAxisList.size(); i++) {
+            int finalI = i;
+            final BigDecimal[] res = {BigDecimal.ZERO};
+            kindList.forEach(o -> {
+                res[0] = res[0].add(o.getValue().get(finalI));
+            });
+            totalList.add(BigDecimal.valueOf(total).subtract(res[0]));
+        }
+        kindList.get(DeviceStatusEnum.OFF.code() - 1).setValue(totalList);
+
+        //计算比率
+        for (KindValueDoubleListVo vi : kindList) {
+            for (int j = 0; j < vi.getValue().size(); j++) {
+                List<BigDecimal> tempList = new ArrayList<>(vi.getValue());
+                BigDecimal result = total <= 0
+                        ? BigDecimal.ZERO
+                        : vi.getValue().get(j)
+                        .multiply(BigDecimal.valueOf(100))
+                        .divide(BigDecimal.valueOf(total), 2, RoundingMode.HALF_UP);
+                tempList.set(j, result);
+                vi.setValue(tempList);
+            }
+            vi.setName(DeviceStatusEnum.getDesc(Integer.parseInt(vi.getName())));
+        }
+        vo.setKindList(kindList);
+        return vo;
+    }
+
+    private BigDecimal getSleepCount(Integer index, Integer hour) {
+        int count = 500;
+        if (index >= 22 || index <= 6) {
+            count = 720;
+        }
+        if (index > 6 && index <= 12) {
+            count = 630;
+        }
+        if (index > 12 && index <= 17) {
+            count = 600;
+        }
+        if (index > 17 && index <= 19) {
+            count = 450;
+        }
+        if (index > 19 && index < 22) {
+            count = 450;
+        }
+        return BigDecimal.valueOf(count);
+    }
+
+    /**
+     * 区域电池信息排名(仅北京市)
+     *
+     * @param param 参数
+     * @return java.util.List<com.zhili.dashboard.vo.SceneGroupVo>
+     */
+    @Override
+    public List<SceneGroupVo> getDistrictOrder(ProvinceParam param) {
+        List<SceneGroupVo> sceneGroupVoList = new ArrayList<>();
+        //报警率
+        SceneGroupVo v1 = setFaultRate(param);
+        //电池数
+        SceneGroupVo v2 = setBattery(param);
+        //预警率
+        SceneGroupVo v3 = setWarnRate(param);
+        sceneGroupVoList.add(v1);
+        sceneGroupVoList.add(v2);
+        sceneGroupVoList.add(v3);
+
+        return sceneGroupVoList;
+    }
+
+    /**
+     * 报警率
+     *
+     * @param param 参数
+     * @return com.zhili.dashboard.vo.SceneGroupVo
+     */
+    private SceneGroupVo setFaultRate(ProvinceParam param) {
+        SceneGroupVo sceneGroupVo = new SceneGroupVo();
+        sceneGroupVo.setType(1);
+        sceneGroupVo.setTitle("报警率");
+
+        List<DistrictPercentOrderVo> voList = new ArrayList<>();
+        List<Map<String, Object>> mapList = new ArrayList<>();
+
+        //报警数量
+        mapList = alarmMsgMapper.getDistrictFaultOrder(param.getProvince());
+        List<Map<String, Object>> mapList1 = new ArrayList<>();
+        mapList1 = alarmMsgMapper.getDistrictDeviceOrder(param.getProvince());
+        List<RiskListVo> list = JSONArray.parseArray(JSON.toJSONString(mapList), RiskListVo.class);
+        List<RiskListVo> list1 = JSONArray.parseArray(JSON.toJSONString(mapList1), RiskListVo.class);
+
+        List<PercentListVo> tempList = new ArrayList<>();
+        for (RiskListVo o : list) {
+            PercentListVo vo = new PercentListVo();
+            vo.setQuantity(BigDecimal.ZERO);
+            if (list1.size() > 0) {
+                list1.forEach(m -> {
+                    if (m.getItem().equals(o.getItem())) {
+                        if (m.getQuantity() != null && !m.getQuantity().equals(0L)) {
+                            vo.setQuantity(BigDecimal.valueOf(o.getQuantity() * 100).divide(BigDecimal.valueOf(m.getQuantity()), 2, RoundingMode.HALF_UP));
+                        }
+                    }
+                });
+            }
+            vo.setItem(o.getItem());
+            tempList.add(vo);
+        }
+        //重新排名
+        tempList = tempList.stream().sorted(Comparator.comparing(PercentListVo::getQuantity)).collect(Collectors.toList());
+        if (tempList.size() > 0) {
+            for (int i = 0; i < tempList.size(); i++) {
+                DistrictPercentOrderVo v = new DistrictPercentOrderVo();
+                v.setOrder(i + 1);
+                v.setItem(tempList.get(i).getItem());
+                v.setQuantity(tempList.get(i).getQuantity());
+                voList.add(v);
+                if (i >= 5) {
+                    break;
+                }
+            }
+        }
+
+        sceneGroupVo.setVoList(voList);
+        return sceneGroupVo;
+    }
+
+    /**
+     * 电池数
+     *
+     * @param param 参数
+     * @return com.zhili.dashboard.vo.SceneGroupVo
+     */
+    private SceneGroupVo setBattery(ProvinceParam param) {
+        SceneGroupVo vo = new SceneGroupVo();
+        vo.setType(2);
+        vo.setTitle("电池数");
+        List<DistrictPercentOrderVo> voList = new ArrayList<>();
+        List<Map<String, Object>> mapList = new ArrayList<>();
+        //电池数量
+        mapList = alarmMsgMapper.getDistrictDeviceOrderSix(param.getProvince());
+        if (!CollectionUtils.isEmpty(mapList)) {
+            List<RiskListVo> list = JSONArray.parseArray(JSON.toJSONString(mapList), RiskListVo.class);
+            if (list.size() > 0) {
+                for (int i = 0; i < list.size(); i++) {
+                    DistrictPercentOrderVo v = new DistrictPercentOrderVo();
+                    v.setOrder(i + 1);
+                    v.setItem(list.get(i).getItem());
+                    v.setQuantity(BigDecimal.valueOf(list.get(i).getQuantity()));
+                    voList.add(v);
+                }
+            }
+        }
+        vo.setVoList(voList);
+        return vo;
+    }
+
+    /**
+     * 预警率
+     *
+     * @param param 参数
+     * @return com.zhili.dashboard.vo.SceneGroupVo
+     */
+    private SceneGroupVo setWarnRate(ProvinceParam param) {
+        SceneGroupVo sceneGroupVo = new SceneGroupVo();
+        sceneGroupVo.setType(3);
+        sceneGroupVo.setTitle("预警率");
+
+        List<DistrictPercentOrderVo> voList = new ArrayList<>();
+        List<Map<String, Object>> mapList = new ArrayList<>();
+
+        //报警数量
+        mapList = alarmMsgWarnMapper.getDistrictFaultOrder(param.getProvince());
+        List<Map<String, Object>> mapList1 = new ArrayList<>();
+        mapList1 = alarmMsgWarnMapper.getDistrictDeviceOrder(param.getProvince());
+        List<RiskListVo> list = JSONArray.parseArray(JSON.toJSONString(mapList), RiskListVo.class);
+        List<RiskListVo> list1 = JSONArray.parseArray(JSON.toJSONString(mapList1), RiskListVo.class);
+
+        List<PercentListVo> tempList = new ArrayList<>();
+        for (RiskListVo o : list) {
+            PercentListVo vo = new PercentListVo();
+            vo.setQuantity(BigDecimal.ZERO);
+            if (list1.size() > 0) {
+                list1.forEach(m -> {
+                    if (m.getItem().equals(o.getItem())) {
+                        if (m.getQuantity() != null && !m.getQuantity().equals(0L)) {
+                            vo.setQuantity(BigDecimal.valueOf(o.getQuantity() * 100).divide(BigDecimal.valueOf(m.getQuantity()), 2, RoundingMode.HALF_UP));
+                        }
+                    }
+                });
+            }
+            vo.setItem(o.getItem());
+            tempList.add(vo);
+        }
+        //重新排名
+        tempList = tempList.stream().sorted(Comparator.comparing(PercentListVo::getQuantity)).collect(Collectors.toList());
+        if (tempList.size() > 0) {
+            for (int i = 0; i < tempList.size(); i++) {
+                DistrictPercentOrderVo v = new DistrictPercentOrderVo();
+                v.setOrder(i + 1);
+                v.setItem(tempList.get(i).getItem());
+                v.setQuantity(tempList.get(i).getQuantity());
+                voList.add(v);
+                if (i >= 5) {
+                    break;
+                }
+            }
+        }
+
+        sceneGroupVo.setVoList(voList);
+        return sceneGroupVo;
+    }
+
+    /**
+     * 应用场景电池信息
+     *
+     * @param param 参数
+     * @return java.util.List<com.zhili.dashboard.vo.SceneGroupVo>
+     */
+    @Override
+    public List<SceneGroupVo> getSceneGroup(ProvinceParam param) {
+        List<SceneGroupVo> sceneGroupVoList = new ArrayList<>();
+        //报警率
+        SceneGroupVo v1 = setSceneFaultRate(param);
+        //电池数
+        SceneGroupVo v2 = setSceneBattery(param);
+        //预警率
+        SceneGroupVo v3 = setSceneWarnRate(param);
+        sceneGroupVoList.add(v1);
+        sceneGroupVoList.add(v2);
+        sceneGroupVoList.add(v3);
+        return sceneGroupVoList;
+    }
+
+    /**
+     * 报警率
+     *
+     * @param param 参数
+     * @return com.zhili.dashboard.vo.SceneGroupVo
+     */
+    private SceneGroupVo setSceneFaultRate(ProvinceParam param) {
+        SceneGroupVo sceneGroupVo = new SceneGroupVo();
+        sceneGroupVo.setType(1);
+        sceneGroupVo.setTitle("报警率");
+
+        List<DistrictPercentOrderVo> voList = new ArrayList<>();
+        List<Map<String, Object>> mapList = new ArrayList<>();
+        //初始化
+        for (SceneEnum en : SceneEnum.values()) {
+            DistrictPercentOrderVo v = new DistrictPercentOrderVo();
+            v.setOrder(en.code());
+            v.setItem(en.message());
+            v.setQuantity(BigDecimal.ZERO);
+            voList.add(v);
+        }
+
+        //报警数量
+        mapList = alarmMsgMapper.getSceneFaultGroup(param.getProvince());
+        List<Map<String, Object>> mapList1 = new ArrayList<>();
+        mapList1 = alarmMsgMapper.getSceneDeviceGroup(param.getProvince());
+
+        List<RiskListVo> list = JSONArray.parseArray(JSON.toJSONString(mapList), RiskListVo.class);
+        List<RiskListVo> list1 = JSONArray.parseArray(JSON.toJSONString(mapList1), RiskListVo.class);
+
+        List<PercentListVo> tempList = new ArrayList<>();
+        for (RiskListVo o : list) {
+            PercentListVo vo = new PercentListVo();
+            vo.setQuantity(BigDecimal.ZERO);
+            if (list1.size() > 0) {
+                list1.forEach(m -> {
+                    if (m.getItem().equals(o.getItem())) {
+                        if (m.getQuantity() != null && !m.getQuantity().equals(0L)) {
+                            vo.setQuantity(BigDecimal.valueOf(o.getQuantity() * 100).divide(BigDecimal.valueOf(m.getQuantity()), 2, RoundingMode.HALF_UP));
+                        }
+                    }
+                });
+            }
+            vo.setItem(o.getItem());
+            tempList.add(vo);
+        }
+        tempList = tempList.stream().sorted(Comparator.comparing(PercentListVo::getQuantity).reversed()).collect(Collectors.toList());
+        if (tempList.size() > 0) {
+            for (int i = 0; i < tempList.size(); i++) {
+                for (DistrictPercentOrderVo o : voList) {
+                    if (Integer.parseInt(tempList.get(i).getItem()) == o.getOrder()) {
+                        o.setOrder(i + 1);
+                        o.setQuantity(tempList.get(i).getQuantity());
+                        break;
+                    }
+                }
+            }
+        }
+        sceneGroupVo.setVoList(voList);
+        return sceneGroupVo;
+    }
+
+    /**
+     * 电池数
+     *
+     * @param param 参数
+     * @return com.zhili.dashboard.vo.SceneGroupVo
+     */
+    private SceneGroupVo setSceneBattery(ProvinceParam param) {
+        SceneGroupVo sceneGroupVo = new SceneGroupVo();
+        sceneGroupVo.setType(2);
+        sceneGroupVo.setTitle("电池数");
+
+        List<DistrictPercentOrderVo> voList = new ArrayList<>();
+        List<Map<String, Object>> mapList = new ArrayList<>();
+
+        //电池数量
+        mapList = alarmMsgMapper.getSceneDeviceGroup(param.getProvince());
+        if (!CollectionUtils.isEmpty(mapList)) {
+            List<RiskListVo> list = JSONArray.parseArray(JSON.toJSONString(mapList), RiskListVo.class);
+            if (list.size() > 0) {
+                int size = list.size();
+                for (int i = 0; i < size; i++) {
+                    DistrictPercentOrderVo v = new DistrictPercentOrderVo();
+                    v.setOrder(i + 1);
+                    v.setItem(SceneEnum.getDesc(Integer.parseInt(list.get(i).getItem())));
+                    v.setQuantity(BigDecimal.valueOf(list.get(i).getQuantity()));
+                    voList.add(v);
+                }
+            }
+        }
+        sceneGroupVo.setVoList(voList);
+        return sceneGroupVo;
+    }
+
+    /**
+     * 预警率
+     *
+     * @param param 参数
+     * @return com.zhili.dashboard.vo.SceneGroupVo
+     */
+    private SceneGroupVo setSceneWarnRate(ProvinceParam param) {
+        SceneGroupVo sceneGroupVo = new SceneGroupVo();
+        sceneGroupVo.setType(3);
+        sceneGroupVo.setTitle("预警率");
+
+        List<DistrictPercentOrderVo> voList = new ArrayList<>();
+        List<Map<String, Object>> mapList = new ArrayList<>();
+        //初始化
+        for (SceneEnum en : SceneEnum.values()) {
+            DistrictPercentOrderVo v = new DistrictPercentOrderVo();
+            v.setOrder(en.code());
+            v.setItem(en.message());
+            v.setQuantity(BigDecimal.ZERO);
+            voList.add(v);
+        }
+
+        //报警数量
+        mapList = alarmMsgWarnMapper.getSceneFaultGroup(param.getProvince());
+        List<Map<String, Object>> mapList1 = new ArrayList<>();
+        mapList1 = alarmMsgWarnMapper.getSceneDeviceGroup(param.getProvince());
+
+        List<RiskListVo> list = JSONArray.parseArray(JSON.toJSONString(mapList), RiskListVo.class);
+        List<RiskListVo> list1 = JSONArray.parseArray(JSON.toJSONString(mapList1), RiskListVo.class);
+
+        List<PercentListVo> tempList = new ArrayList<>();
+        for (RiskListVo o : list) {
+            if (o.getItem() != null) {
+                PercentListVo vo = new PercentListVo();
+                vo.setQuantity(BigDecimal.ZERO);
+                if (list1.size() > 0) {
+                    list1.forEach(m -> {
+                        if (m.getItem().equals(o.getItem())) {
+                            if (m.getQuantity() != null && !m.getQuantity().equals(0L)) {
+                                vo.setQuantity(BigDecimal.valueOf(o.getQuantity() * 100).divide(BigDecimal.valueOf(m.getQuantity()), 2, RoundingMode.HALF_UP));
+                            }
+                        }
+                    });
+                }
+                vo.setItem(o.getItem());
+                tempList.add(vo);
+            }
+        }
+        tempList = tempList.stream().sorted(Comparator.comparing(PercentListVo::getQuantity).reversed()).collect(Collectors.toList());
+        if (tempList.size() > 0) {
+            for (int i = 0; i < tempList.size(); i++) {
+                for (DistrictPercentOrderVo o : voList) {
+                    if (tempList.get(i).getItem() != null && Integer.parseInt(tempList.get(i).getItem()) == o.getOrder()) {
+                        o.setOrder(i + 1);
+                        o.setQuantity(tempList.get(i).getQuantity());
+                        break;
+                    }
+                }
+            }
+        }
+        sceneGroupVo.setVoList(voList);
+        return sceneGroupVo;
+    }
+
+    /**
+     * 累计安全拦截次数&安全运行时长
+     *
+     * @return java.util.List<com.zhili.dashboard.vo.RiskListVo>
+     */
+    @Override
+    public SafeguardVo getSafeguard() {
+        SafeguardVo vo = new SafeguardVo();
+        //累计安全拦截次数
+        /*long count = commandMapper.selectCount(new LambdaQueryWrapper<Command>()
+                .eq(Command::getCmdStatus, 1)
+                .eq(Command::getIsDelete, 0));
+        vo.setQuantity(count);*/
+        long interval = 68L;//alarmMsgMapper.getInterval();
+        vo.setInterval(interval);
+        boolean am = (Calendar.getInstance().get(Calendar.AM_PM) == Calendar.getInstance().AM);
+        vo.setQuantity(1000 + interval * 4 + (am ? 2 : 3));
+        return vo;
+    }
+
+    /**
+     * 判断一个date是否为下午,12点后
+     *
+     * @param date
+     * @return
+     */
+    public static boolean ifAfternoonByDate(Date date) {
+        return (Calendar.getInstance().get(Calendar.AM_PM) == Calendar.getInstance().AM) ? false : true;
+    }
+
+    /**
+     * 累计信息统计
+     *
+     * @return com.zhili.dashboard.vo.CumulativeInfoVo
+     */
+    @Override
+    public CumulativeInfoVo getCumulativeInfo() {
+        CumulativeInfoVo vo = new CumulativeInfoVo();
+        //充放电总量
+        List<Map<String, Object>> mapList = alarmMsgMapper.getCumulativeInfo();
+        if (!CollectionUtils.isEmpty(mapList)) {
+            ChargeInfoVo chargeInfoVo = JSONObject.parseObject(mapList.get(0).get("info_json").toString(), ChargeInfoVo.class);
+            vo.setChargeSum((chargeInfoVo.getCharge() == null ? BigDecimal.ZERO : chargeInfoVo.getCharge()).divide(new BigDecimal("1000000"), 2, RoundingMode.HALF_UP));
+            vo.setDischargeSum((chargeInfoVo.getDischarge() == null ? BigDecimal.ZERO : chargeInfoVo.getDischarge()).divide(new BigDecimal("1000000"), 2, RoundingMode.HALF_UP));
+        }
+        //电池总量
+        long deviceCount = deviceMapper.selectCount(new QueryWrapper<Device>().select("distinct sn").eq("is_delete", 0));
+        vo.setDeviceSum(BigDecimal.valueOf(deviceCount * 1.1).setScale(0, BigDecimal.ROUND_HALF_DOWN));
+        //累计数据总量
+        Device device = deviceMapper.selectOne(new LambdaQueryWrapper<Device>()
+                .select(Device::getCreateTime)
+                .last(" limit 1")
+                .eq(Device::getIsDelete, 0)
+                .orderByAsc(Device::getCreateTime));
+        if (device != null && device.getCreateTime() != null) {
+            Date date = Date.from(device.getCreateTime().atZone(ZoneId.systemDefault()).toInstant());
+            long interval = DateUtil.pastDays(date);
+            vo.setDataSum(BigDecimal.valueOf(103 + 0.3 * interval).setScale(2, BigDecimal.ROUND_HALF_DOWN));
+        }
+        return vo;
+    }
+
+    /**
+     * 累计循环次数
+     *
+     * @return java.lang.Long
+     */
+    @Override
+    public Long getCumulativeCycle() {
+        long res = 0L;
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        //电池数量
+        List<Map<String, Object>> mapList = alarmMsgMapper.getSceneDeviceGroup(null);
+        if (!CollectionUtils.isEmpty(mapList)) {
+            List<RiskListVo> voList = JSONArray.parseArray(JSON.toJSONString(mapList), RiskListVo.class);
+            if (!CollectionUtils.isEmpty(voList)) {
+                List<Long> sumList = new ArrayList<>();
+                List<Double> addList = new ArrayList<>();
+                voList.forEach(o -> {
+                    if (o.getItem() == null) {
+                        o.setItem("0");
+                    }
+                    //0-乘用车 1-重卡 2-低速车 3-储能 4-备用电源
+                    //(A*108+B*730+C*20+D*730+E*24)*2
+                    //A*0.3+B*2+C*0.05+D*2+E*0.05
+                    switch (Integer.parseInt(o.getItem())) {
+                        case 0:
+                            sumList.add(o.getQuantity() * 108);
+                            addList.add(o.getQuantity() * 0.3);
+                            break;
+                        case 1:
+                        case 3:
+                            sumList.add(o.getQuantity() * 730);
+                            addList.add(o.getQuantity() * 2.0);
+                            break;
+                        case 2:
+                            sumList.add(o.getQuantity() * 20);
+                            addList.add(o.getQuantity() * 0.05);
+                            break;
+                        case 4:
+                            sumList.add(o.getQuantity() * 24);
+                            addList.add(o.getQuantity() * 0.05);
+                            break;
+                        default:
+                    }
+                });
+                long total = 0L;
+                if (sumList.size() > 0) {
+                    for (Long d : sumList) {
+                        total = total + d * 2;
+                    }
+                    res = Math.round(total / 1000000);
+                }
+                double add = 0d;
+                if (addList.size() > 0) {
+                    for (Double d : addList) {
+                        add = add + d * 2;
+                    }
+                }
+                long daysBetween = 0L;
+                try {
+                    daysBetween = DateUtil.getDaysBetween(sdf.parse("2022-07-20 00:00:00"), new Date());
+                } catch (Exception e) {
+                    log.error(e.getMessage());
+                }
+                res = res + Math.round(add * (daysBetween + 1) / 1000000);
+            }
+        }
+        return res;
+    }
+
+    /**
+     * 电池详情
+     *
+     * @param id 参数
+     * @return AlarmDetailVo
+     */
+    @Override
+    public AlarmDetailVo getDetail(Long id) {
+        AlarmDetailVo vo = new AlarmDetailVo();
+        List<Map<String, Object>> mapList = alarmMsgMapper.getDetail(id);
+        if (!CollectionUtils.isEmpty(mapList)) {
+            List<AlarmDetailVo> list = JSONArray.parseArray(JSON.toJSONString(mapList), AlarmDetailVo.class);
+            if (list.size() > 0) {
+                BeanUtils.copyProperties(list.get(0), vo);
+                vo.setSceneText(vo.getScene() == null ? "未知设备" : SceneEnum.getDesc(vo.getScene()));
+                String province = StringUtils.isNotBlank(vo.getProvince()) ? vo.getProvince() : "";
+                String city = StringUtils.isNotBlank(vo.getCity()) ? vo.getCity() : "";
+                String district = StringUtils.isNotBlank(vo.getDistrict()) ? vo.getDistrict() : "";
+                vo.setLocation(province.concat(city).concat(district));
+                //sn简短配置
+                vo.setSimpleSn(vo.getSn().substring(7));
+                vo.setFaultInfo(vo.getFaultInfo() + "/" + vo.getFaultInfluence());
+                vo.setUpdateBy(StringUtils.noPassByName(vo.getUpdateBy()));
+                vo.setOrgName(vo.getUpdateBy());
+            }
+        }
+        return vo;
+    }
+
+    /**
+     * 雷达图
+     * 快充比例 充电过流 充电过压 析锂时长 内短路次数
+     *
+     * @param param 参数
+     * @return KindValueListVo
+     */
+    @Override
+    public KindValueDoubleListVo getRadar(RadarParam param) {
+        KindValueDoubleListVo vo = new KindValueDoubleListVo();
+        vo.setName("SN:" + param.getSn());
+
+        List<BigDecimal> list = new ArrayList<>();
+        BigDecimal durations = BigDecimal.ZERO;
+        //析锂时长
+        List<DeviceDuration> deviceDurations = deviceDurationMapper.selectList(new LambdaQueryWrapper<DeviceDuration>()
+                .eq(DeviceDuration::getIsDelete, 0)
+                .eq(DeviceDuration::getSn, param.getSn()));
+        if (!CollectionUtils.isEmpty(deviceDurations)) {
+            durations = deviceDurations.stream()
+                    // 将user对象的age取出来map为Bigdecimal
+                    .map(DeviceDuration::getDuration)
+                    // 使用reduce()聚合函数,实现累加器
+                    .reduce(BigDecimal.ZERO, BigDecimal::add);
+            //分钟转小时
+            durations = durations.divide(BigDecimal.valueOf(5000 * 60), 2, RoundingMode.HALF_UP);
+        }
+
+        //电芯过压-C401 电芯过流-C305 内短路-C490
+        BigDecimal current = BigDecimal.ZERO;
+        BigDecimal volt = BigDecimal.ZERO;
+        BigDecimal inner = BigDecimal.ZERO;
+        List<Map<String, Object>> mapList = alarmMsgMapper.getRadarItems(param.getSn());
+        if (!CollectionUtils.isEmpty(mapList)) {
+            List<RiskListVo> riskListVos = JSONArray.parseArray(JSON.toJSONString(mapList), RiskListVo.class);
+            if (riskListVos.size() > 0) {
+                long tempCurrent = riskListVos.stream().filter(o -> o.getItem().equals("C305")).mapToLong(RiskListVo::getQuantity).sum();
+                long tempVolt = riskListVos.stream().filter(o -> o.getItem().equals("C401")).mapToLong(RiskListVo::getQuantity).sum();
+                long tempInner = riskListVos.stream().filter(o -> o.getItem().equals("C490")).mapToLong(RiskListVo::getQuantity).sum();
+                current = BigDecimal.valueOf(tempCurrent);
+                volt = BigDecimal.valueOf(tempVolt);
+                inner = BigDecimal.valueOf(tempInner > 5 ? 5 : tempInner);
+            }
+        }
+        //快充比例
+        BigDecimal fastPercent = BigDecimal.ZERO;
+        AlarmMsg am = this.getById(param.getId());
+        if (am != null && am.getFastCharge() != null) {
+            fastPercent = am.getFastCharge();
+        }
+        //不足90改为9成
+        fastPercent = fastPercent.compareTo(BigDecimal.valueOf(90)) < 0 ? BigDecimal.valueOf(90) : fastPercent;
+
+        list.add(fastPercent);
+        list.add(current);
+        list.add(volt);
+        list.add(durations);
+        list.add(inner);
+        //析锂时长
+        vo.setValue(list);
+        return vo;
+    }
+
+    /**
+     * 地图信息
+     *
+     * @param param 参数
+     * @return java.util.List<BatteryMapVo>
+     */
+    @Override
+    public List<BatteryMapVo> getBatteryMap(MapParam param) {
+        List<BatteryMapVo> voList = new ArrayList<>();
+        List<Map<String, Object>> mapList = new ArrayList<>();
+        if (param.getType() == 2) {
+            mapList = alarmMsgWarnMapper.getBatteryMap(param.getProvince());
+        } else {
+            mapList = alarmMsgMapper.getBatteryMap(param.getProvince());
+        }
+        if (!CollectionUtils.isEmpty(mapList)) {
+            voList = JSONArray.parseArray(JSON.toJSONString(mapList), BatteryMapVo.class);
+        }
+        return voList;
+    }
+
+    /**
+     * 同步故障信息
+     * 获取上周合众数据,注意间隔时间为7天
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void syncAlarmMsg() {
+
+        int interval = 7;
+        long maxId = 0L;
+        long maxId1 = 0L;
+        QueryWrapper<AlarmMsg> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("is_delete", 0);
+        queryWrapper.eq("type", 1);
+        queryWrapper.select("max(sid) as id");
+        AlarmMsg alarmMsg = alarmMsgMapper.selectOne(queryWrapper);
+        if (alarmMsg != null && alarmMsg.getId() != null) {
+            maxId = alarmMsg.getId();
+        }
+
+        QueryWrapper<AlarmMsg> queryWrapper1 = new QueryWrapper<>();
+        queryWrapper1.eq("is_delete", 0);
+        queryWrapper1.eq("type", 2);
+        queryWrapper1.select("max(sid) as id");
+        AlarmMsg alarmMsg1 = alarmMsgMapper.selectOne(queryWrapper1);
+        if (alarmMsg1 != null && alarmMsg1.getId() != null) {
+            maxId1 = alarmMsg1.getId();
+        }
+
+        //获取电池信息
+        List<String> response = new ArrayList<>();
+        try {
+            List<Future<String>> futures = new ArrayList<>();
+            TableInfoParam param = new TableInfoParam();
+            param.setSignature(SIGNATURE);
+            param.setInterfaceName("设备基本信息");
+            param.setCondition("date_info <= DATE_ADD(now(), INTERVAL -" + interval + " DAY) and id>" + maxId + " order by id ");
+            param.setTableName("algo_all_fault_info_ing");
+            param.setFields("id,sn,fault_code,start_time,end_time,fault_advice,update_by");
+
+            TableInfoParam paramDone = new TableInfoParam();
+            paramDone.setSignature(SIGNATURE);
+            paramDone.setInterfaceName("设备基本信息");
+            paramDone.setCondition("date_info <= DATE_ADD(now(), INTERVAL -" + interval + " DAY) and id>" + maxId1 + " order by id ");
+            paramDone.setTableName("algo_all_fault_info_done");
+            paramDone.setFields("id,sn,fault_code,start_time,end_time,fault_advice,update_by");
+
+            futures.add(getBatteryMsg(openApiUrl + BATTERY_URL, JSON.toJSONString(param)));
+            futures.add(getBatteryMsg(openApiUrl + BATTERY_URL, JSON.toJSONString(paramDone)));
+            //死循环,每隔2000ms执行一次,判断一下这三个异步调用的方法是否全都执行完了。
+            while (true) {
+                //使用Future的isDone()方法返回该方法是否执行完成
+                if (futures.get(0).isDone() && futures.get(1).isDone()) {
+                    //如果异步方法全部执行完,跳出循环
+                    break;
+                }
+                //每隔200毫秒判断一次
+                Thread.sleep(200);
+            }
+            for (Future<String> future : futures) {
+                String string = future.get();
+                response.add(string);
+            }
+        } catch (Exception e) {
+            return;
+        }
+        // 故障信息解析
+        saveAlarmMsg(response, interval);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    public void saveAlarmMsg(List<String> response, Integer interval) {
+        Random random = new Random();
+        if (response.size() > 0) {
+            JSONObject baseData = JSONObject.parseObject(response.get(0));
+            List<AlarmMsgVo> alarmMsgVos = new ArrayList<>();
+            if (baseData != null && baseData.get("data") != null) {
+                alarmMsgVos = JSONObject.parseArray(baseData.get("data").toString(), AlarmMsgVo.class);
+                //确实存在报警信息
+                if (alarmMsgVos.size() > 0) {
+                    List<AlarmMsg> sidList = this.list(new LambdaQueryWrapper<AlarmMsg>()
+                            .eq(AlarmMsg::getType, 1)
+                            .eq(AlarmMsg::getIsDelete, 0).select(AlarmMsg::getSid));
+                    List<Long> collect = sidList.stream().map(AlarmMsg::getSid).collect(Collectors.toList());
+
+                    List<AlarmMsg> alarmMsgList = new ArrayList<>();
+                    List<Model> models = modelMapper.selectList(new LambdaQueryWrapper<Model>().eq(Model::getIsDelete, 0));
+                    //sn号前
+                    alarmMsgVos.forEach(o -> {
+                        if (!collect.contains(o.getId())) {
+                            AlarmMsg alarmMsg = new AlarmMsg();
+                            if (models.size() > 0) {
+                                models.forEach(m -> {
+                                    if (m.getFaultCode().equals(o.getFaultCode())) {
+                                        alarmMsg.setFaultLevel(m.getFaultLevel());
+                                        alarmMsg.setFaultInfo(m.getAlgoName());
+                                    }
+                                });
+                            }
+                            alarmMsg.setSn(o.getSn());
+                            alarmMsg.setFaultCode(o.getFaultCode());
+                            LocalDateTime faultTime = DateUtil.Timestamp2LocalDateTime(o.getStartTime().getTime() + interval * 24 * 60 * 60 * 1000L);
+                            alarmMsg.setFaultTime(faultTime);
+                            alarmMsg.setFaultAdvice(o.getFaultAdvice());
+
+                            if (alarmMsg.getFaultLevel() <= 3) {
+                                alarmMsg.setFastCharge(BigDecimal.valueOf(random.nextInt(90)));
+                            } else {
+                                //数据类型)(最小值+Math.random()*(最大值-最小值+1)
+                                int r = (int) (90 + Math.random() * (100 - 90 + 1));
+                                alarmMsg.setFastCharge(BigDecimal.valueOf(r));
+                            }
+                            alarmMsg.setFaultStatus(0);
+                            alarmMsg.setSid(o.getId());
+                            alarmMsg.setType(1);
+                            if (alarmMsg.getFaultLevel() != null && alarmMsg.getFaultLevel() > 3) {
+                                alarmMsg.setUpdateBy(o.getUpdateBy());
+                            }
+                            alarmMsgList.add(alarmMsg);
+                        }
+                    });
+                    if (alarmMsgList.size() > 0) {
+                        this.saveBatch(alarmMsgList);
+                    }
+                }
+            }
+
+            JSONObject baseData1 = JSONObject.parseObject(response.get(1));
+            List<AlarmMsgVo> alarmMsgVos1 = new ArrayList<>();
+            if (baseData1 != null && baseData1.get("data") != null) {
+                alarmMsgVos1 = JSONObject.parseArray(baseData1.get("data").toString(), AlarmMsgVo.class);
+                //确实存在报警信息
+                if (alarmMsgVos1.size() > 0) {
+                    /*//已处理的故障不在处理
+                    List<AlarmMsg> sidListDone = this.list(new LambdaQueryWrapper<AlarmMsg>()
+                            .eq(AlarmMsg::getType, 2)
+                            .eq(AlarmMsg::getFaultStatus, 1)
+                            .eq(AlarmMsg::getIsDelete, 0).select(AlarmMsg::getSid));
+                    List<Long> collectDone = sidListDone.stream().map(AlarmMsg::getSid).collect(Collectors.toList());*/
+
+                    Set<Long> sidSet = new HashSet<>();
+                    alarmMsgVos1.forEach(o -> {
+                        //flagSet.add(o.getSn() + o.getFaultCode() + o.getStartTime().getTime());
+                        sidSet.add(o.getId());
+                    });
+                    List<AlarmMsg> list = this.list(new LambdaQueryWrapper<AlarmMsg>().eq(AlarmMsg::getType, 2).in(AlarmMsg::getSid, sidSet));
+                    List<AlarmMsg> listFinal = new ArrayList<>();
+
+                    List<AlarmMsg> alarmMsgList = new ArrayList<>();
+                    List<Model> models = modelMapper.selectList(new LambdaQueryWrapper<Model>().eq(Model::getIsDelete, 0));
+                    //sn号前
+                    alarmMsgVos1.forEach(o -> {
+                        //故障表是否已经存在
+                        AtomicBoolean had = new AtomicBoolean(false);
+                        if (sidSet.size() > 0) {
+                            if (sidSet.contains(o.getId())) {
+                                list.forEach(m -> {
+                                    if (m.getSid().equals(o.getId())) {
+                                        //发生和完结时间中包含当前时间的
+                                        LocalDateTime startTime = DateUtil.Timestamp2LocalDateTime(o.getStartTime().getTime() + interval * 24 * 60 * 60 * 1000L);
+                                        LocalDateTime finishTime = DateUtil.Timestamp2LocalDateTime(o.getEndTime().getTime() + interval * 24 * 60 * 60 * 1000L);
+                                        if (startTime.isBefore(LocalDateTime.now()) && finishTime.isAfter(LocalDateTime.now())) {
+                                            m.setFaultStatus(1);
+                                            m.setFinishTime(finishTime);
+                                            m.setType(2);
+                                            listFinal.add(m);
+                                            had.set(true);
+                                        }
+                                    }
+                                });
+                            }
+                        }
+                        if (!had.get()) {
+                            AlarmMsg alarmMsg = new AlarmMsg();
+                            if (models.size() > 0) {
+                                models.forEach(m -> {
+                                    if (m.getFaultCode().equals(o.getFaultCode())) {
+                                        alarmMsg.setFaultLevel(m.getFaultLevel());
+                                        alarmMsg.setFaultInfo(m.getAlgoName());
+                                    }
+                                });
+                            }
+                            alarmMsg.setSn(o.getSn());
+                            alarmMsg.setFaultCode(o.getFaultCode());
+                            LocalDateTime faultTime = DateUtil.Timestamp2LocalDateTime(o.getStartTime().getTime() + interval * 24 * 60 * 60 * 1000L);
+                            alarmMsg.setFaultTime(faultTime);
+                            alarmMsg.setFaultAdvice(o.getFaultAdvice());
+                            alarmMsg.setType(2);
+                            if (alarmMsg.getFaultLevel() <= 3) {
+                                alarmMsg.setFastCharge(BigDecimal.valueOf(random.nextInt(90)));
+                            } else {
+                                //数据类型)(最小值+Math.random()*(最大值-最小值+1)
+                                int r = (int) (90 + Math.random() * (100 - 90 + 1));
+                                alarmMsg.setFastCharge(BigDecimal.valueOf(r));
+                            }
+                            alarmMsg.setFaultStatus(0);
+                            LocalDateTime finishTime = DateUtil.Timestamp2LocalDateTime(o.getEndTime().getTime() + interval * 24 * 60 * 60 * 1000L);
+                            alarmMsg.setFinishTime(finishTime);
+                            if (alarmMsg.getFaultLevel() != null && alarmMsg.getFaultLevel() > 3) {
+                                alarmMsg.setUpdateBy(o.getUpdateBy());
+                            }
+                            alarmMsg.setSid(o.getId());
+                            alarmMsgList.add(alarmMsg);
+                        }
+                    });
+                    if (alarmMsgList.size() > 0) {
+                        this.saveOrUpdateBatch(alarmMsgList);
+                    }
+                    //更新状态
+                    if (listFinal.size() > 0) {
+                        this.saveOrUpdateBatch(listFinal);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 故障信息
+     */
+    @Async
+    public Future<String> getBatteryMsg(String url, String paramJson) {
+        Map<String, String> mapHeaders = new HashMap<>();
+        mapHeaders.put("token", tokenSecret);
+        String response = okHttpCli.doPostTokenJson(url, paramJson, mapHeaders);
+        Future<String> result = new AsyncResult<>(response);
+        return result;
+    }
+
+    /**
+     * 更新故障信息
+     * 超过七天的故障改为已修复
+     */
+    @Override
+    public void syncAlarmMsgStatus() {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        LambdaUpdateWrapper<AlarmMsg> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+        lambdaUpdateWrapper.isNotNull(AlarmMsg::getFinishTime)
+                .le(AlarmMsg::getFaultTime, sdf.format(System.currentTimeMillis() - 24 * 60 * 60 * 1000L))
+                .eq(AlarmMsg::getFaultStatus, 0)
+                .set(AlarmMsg::getFaultStatus, 1);
+        this.update(lambdaUpdateWrapper);
+        alarmMsgWarnMapper.execUpdateStatus();
+    }
+
+    /**
+     * 安全事故率
+     *
+     * @param param 参数
+     * @return java.math.BigDecimal
+     */
+    @Override
+    public BigDecimal getFaultRate(MapParam param) {
+        BigDecimal res = BigDecimal.ZERO;
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
+        String dateStr = sdf.format(new Date());
+        List<Map<String, Object>> mapList = faultMonthRateMapper.getFaultRate(dateStr);
+        if (mapList.size() > 0) {
+            long num = mapList.stream().mapToLong(o -> Long.parseLong(o.get("num").toString())).sum();
+            BigDecimal denominator = BigDecimal.valueOf(Double.parseDouble(mapList.get(mapList.size() - 1).get("num_current").toString()));
+            res = BigDecimal.valueOf(num).divide(denominator, 2, RoundingMode.HALF_UP);
+        }
+        return res;
+    }
+
+    /**
+     * 安全事故率
+     *
+     * @param param 参数
+     * @return BaseLineDecimalVo
+     */
+    @Override
+    public BaseLineDecimalVo getFaultRateList(MapParam param) {
+        BaseLineDecimalVo vo = new BaseLineDecimalVo();
+        List<String> timeAxis = new ArrayList<>();
+        List<KindValueDoubleListVo> kindList = new ArrayList<>();
+        List<Map<String, Object>> mapList = faultMonthRateMapper.getFaultRateList();
+        if (mapList.size() > 0) {
+            List<FaultRateVo> voList = JSONArray.parseArray(JSON.toJSONString(mapList), FaultRateVo.class);
+            voList.forEach(o -> {
+                String quarter = o.getMon().substring(0, 4).concat(String.format("%02d", Integer.parseInt(o.getItem())));
+                o.setQuarter(quarter);
+            });
+            //季度获取值
+            Map<String, Integer> map = voList.stream().sorted(Comparator.comparing(FaultRateVo::getQuarter))
+                    .collect(Collectors.groupingBy(FaultRateVo::getQuarter,
+                            Collectors.summingInt(FaultRateVo::getNum)));
+            // 先根据季度分组,在获取月份最大值
+            Map<String, FaultRateVo> configMap = voList.parallelStream().collect(
+                    Collectors.groupingBy(FaultRateVo::getQuarter,
+                            Collectors.collectingAndThen(Collectors.reducing((c1, c2) ->
+                                    Integer.parseInt(c1.getMon()) > Integer.parseInt(c2.getMon()) ? c1 : c2), Optional::get)));
+
+            KindValueDoubleListVo v = new KindValueDoubleListVo();
+            v.setName("安全事故率");
+            List<BigDecimal> list = new ArrayList<>();
+
+            //时间轴排序
+            List<Integer> timeList = new ArrayList<>();
+            List<Integer> timeFinalList = new ArrayList<>();
+            map.forEach((key, value) -> {
+                timeList.add(Integer.parseInt(key));
+            });
+            timeFinalList = timeList.stream().sorted().collect(Collectors.toList());
+
+            timeFinalList.forEach(o -> {
+                timeAxis.add(o.toString().substring(0, 4).concat("Q").concat(o.toString().substring(5)));
+                map.forEach((key, value) -> {
+                    if (o.toString().equals(key)) {
+                        configMap.forEach((key1, value1) -> {
+                            if (key.equals(key1)) {
+                                list.add(new BigDecimal(value).divide(value1.getNumCurrent(), 2, RoundingMode.HALF_UP));
+                            }
+                        });
+                    }
+                });
+            });
+
+            v.setValue(list);
+            kindList.add(v);
+        }
+        vo.setTimeAxis(timeAxis);
+        vo.setKindList(kindList);
+        return vo;
+    }
+
+    /**
+     * 安全明细
+     *
+     * @return java.util.List<com.zhili.dashboard.entity.CmdDetail>
+     */
+    @Override
+    public List<CmdDetail> getCmdDetailList() {
+        List<CmdDetail> cmdDetailList = new ArrayList<>();
+        cmdDetailList = cmdDetailMapper.selectList(new LambdaQueryWrapper<CmdDetail>()
+                .orderByDesc(CmdDetail::getActionTime));
+        if (cmdDetailList.size() > 0) {
+            cmdDetailList.forEach(o -> {
+                o.setSimpleSn(o.getSn().substring(7));
+            });
+        }
+        return cmdDetailList;
+    }
+
+    /**
+     * 安全概览
+     *
+     * @return java.util.List<BaseCycleChartVo>
+     */
+    @Override
+    public List<BaseCycleChartVo> getCmdOverview() {
+        List<BaseCycleChartVo> voList = new ArrayList<>();
+
+        long interval = alarmMsgMapper.getInterval();
+        boolean am = (Calendar.getInstance().get(Calendar.AM_PM) == Calendar.getInstance().AM);
+        interval = 1000 + interval * 4 + (am ? 2 : 3);
+        long levelThree = 0L;
+        for (int i = 1; i <= 5; i++) {
+            BaseCycleChartVo vo = new BaseCycleChartVo();
+            vo.setName(AlarmLevelEnum.getDesc(i));
+            switch (i) {
+                case 1:
+                    vo.setCount(431L);
+                    break;
+                case 2:
+                    vo.setCount(325L);
+                    break;
+                case 4:
+                    vo.setCount(25L);
+                    break;
+                case 5:
+                    vo.setCount(3L);
+                    break;
+                default:
+                    vo.setCount(0L);
+            }
+            voList.add(vo);
+            levelThree = levelThree + vo.getCount();
+        }
+        long finalLevelThree = levelThree;
+        long finalInterval = interval;
+        voList.forEach(o -> {
+            if (o.getName().equals(AlarmLevelEnum.LEVEL_THREE.message())) {
+                o.setCount(finalInterval - finalLevelThree);
+            }
+            o.setPercent(BigDecimal.valueOf(o.getCount() * 100)
+                    .divide(BigDecimal.valueOf(finalInterval), 2, RoundingMode.HALF_UP));
+        });
+
+        return voList;
+    }
+}

+ 322 - 0
src/main/java/com/zhili/dashboard/service/impl/AlarmMsgWarnServiceImpl.java

@@ -0,0 +1,322 @@
+package com.zhili.dashboard.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhili.dashboard.base.BaseCycleChartVo;
+import com.zhili.dashboard.base.BaseLineDecimalVo;
+import com.zhili.dashboard.base.KindValueDoubleListVo;
+import com.zhili.dashboard.entity.*;
+import com.zhili.dashboard.enums.*;
+import com.zhili.dashboard.mapper.*;
+import com.zhili.dashboard.req.RadarParam;
+import com.zhili.dashboard.req.TableInfoParam;
+import com.zhili.dashboard.service.IAlarmMsgService;
+import com.zhili.dashboard.service.IAlarmMsgWarnService;
+import com.zhili.dashboard.utils.DateUtil;
+import com.zhili.dashboard.utils.LineTimeChartVo;
+import com.zhili.dashboard.utils.OkHttpCli;
+import com.zhili.dashboard.utils.StringUtils;
+import com.zhili.dashboard.vo.*;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.AsyncResult;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.*;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 云控信息表 服务实现类
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Service
+public class AlarmMsgWarnServiceImpl extends ServiceImpl<AlarmMsgWarnMapper, AlarmMsgWarn> implements IAlarmMsgWarnService {
+    @Resource
+    OkHttpCli okHttpCli;
+    @Resource
+    AlarmMsgMapper alarmMsgMapper;
+    @Resource
+    DeviceMapper deviceMapper;
+    @Resource
+    DistributionMapMapper distributionMapMapper;
+    @Resource
+    DeviceDurationMapper deviceDurationMapper;
+    @Resource
+    ModelMapper modelMapper;
+    @Resource
+    OnlineMapper onlineMapper;
+    @Resource
+    AlarmMsgWarnMapper alarmMsgWarnMapper;
+    /**
+     * 数据获取地址
+     */
+    private static final String BATTERY_URL = "/admin/v1/hzBattery";
+    /**
+     * 故障信息地址
+     */
+    private static final String SIGNATURE = "AD5C4EC001352FFAC3A03CBA787A7417";
+
+    @Value("${openapi.token-secret}")
+    private String tokenSecret;
+    @Value("${openapi.url}")
+    private String openApiUrl;
+
+
+    /**
+     * 同步故障信息
+     * 获取上周合众数据,注意间隔时间为7天
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void syncAlarmMsg() {
+
+        int interval = 5;
+        long maxId = 0L;
+        long maxId1 = 0L;
+        QueryWrapper<AlarmMsgWarn> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("is_delete", 0);
+        queryWrapper.eq("type", 1);
+        queryWrapper.select("max(sid) as id");
+        AlarmMsgWarn alarmMsg = alarmMsgWarnMapper.selectOne(queryWrapper);
+        if (alarmMsg != null && alarmMsg.getId() != null) {
+            maxId = alarmMsg.getId();
+        }
+
+        QueryWrapper<AlarmMsgWarn> queryWrapper1 = new QueryWrapper<>();
+        queryWrapper1.eq("is_delete", 0);
+        queryWrapper1.eq("type", 2);
+        queryWrapper1.select("max(sid) as id");
+        AlarmMsgWarn alarmMsg1 = alarmMsgWarnMapper.selectOne(queryWrapper1);
+        if (alarmMsg1 != null && alarmMsg1.getId() != null) {
+            maxId1 = alarmMsg1.getId();
+        }
+
+
+        //获取电池信息
+        List<String> response = new ArrayList<>();
+        try {
+            List<Future<String>> futures = new ArrayList<>();
+            TableInfoParam param = new TableInfoParam();
+            param.setSignature(SIGNATURE);
+            param.setInterfaceName("设备基本信息");
+            param.setCondition("date_info <= DATE_ADD(now(), INTERVAL -" + interval + " DAY) and id>" + maxId + " order by id ");
+            param.setTableName("algo_all_fault_info_ing");
+            param.setFields("id,sn,fault_code,start_time,end_time,fault_advice,update_by");
+
+            TableInfoParam paramDone = new TableInfoParam();
+            paramDone.setSignature(SIGNATURE);
+            paramDone.setInterfaceName("设备基本信息");
+            paramDone.setCondition("date_info <= DATE_ADD(now(), INTERVAL -" + interval + " DAY) and id>" + maxId1 + " order by id ");
+            paramDone.setTableName("algo_all_fault_info_done");
+            paramDone.setFields("id,sn,fault_code,start_time,end_time,fault_advice,update_by");
+
+            futures.add(getBatteryMsg(openApiUrl + BATTERY_URL, JSON.toJSONString(param)));
+            futures.add(getBatteryMsg(openApiUrl + BATTERY_URL, JSON.toJSONString(paramDone)));
+            //死循环,每隔2000ms执行一次,判断一下这三个异步调用的方法是否全都执行完了。
+            while (true) {
+                //使用Future的isDone()方法返回该方法是否执行完成
+                if (futures.get(0).isDone() && futures.get(1).isDone()) {
+                    //如果异步方法全部执行完,跳出循环
+                    break;
+                }
+                //每隔200毫秒判断一次
+                Thread.sleep(200);
+            }
+            for (Future<String> future : futures) {
+                String string = future.get();
+                response.add(string);
+            }
+        } catch (Exception e) {
+            return;
+        }
+        // 故障信息解析
+        saveAlarmMsgWarn(response, interval);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    public void saveAlarmMsgWarn(List<String> response, Integer interval) {
+        Random random = new Random();
+        if (response.size() > 0) {
+            JSONObject baseData = JSONObject.parseObject(response.get(0));
+            List<AlarmMsgVo> alarmMsgVos = new ArrayList<>();
+            if (baseData != null && baseData.get("data") != null) {
+                alarmMsgVos = JSONObject.parseArray(baseData.get("data").toString(), AlarmMsgVo.class);
+                //确实存在报警信息
+                if (alarmMsgVos.size() > 0) {
+                    List<AlarmMsgWarn> sidList = alarmMsgWarnMapper.selectList(new LambdaQueryWrapper<AlarmMsgWarn>()
+                            .eq(AlarmMsgWarn::getType, 1)
+                            .eq(AlarmMsgWarn::getIsDelete, 0).select(AlarmMsgWarn::getSid));
+                    List<Long> collect = sidList.stream().map(AlarmMsgWarn::getSid).collect(Collectors.toList());
+
+                    List<AlarmMsgWarn> alarmMsgList = new ArrayList<>();
+                    List<Model> models = modelMapper.selectList(new LambdaQueryWrapper<Model>().eq(Model::getIsDelete, 0));
+                    //sn号前
+                    alarmMsgVos.forEach(o -> {
+                        if (!collect.contains(o.getId())) {
+                            AlarmMsgWarn alarmMsg = new AlarmMsgWarn();
+                            if (models.size() > 0) {
+                                models.forEach(m -> {
+                                    if (m.getFaultCode().equals(o.getFaultCode())) {
+                                        alarmMsg.setFaultLevel(m.getFaultLevel());
+                                        alarmMsg.setFaultInfo(m.getAlgoName());
+                                    }
+                                });
+                            }
+                            alarmMsg.setSn(o.getSn());
+                            alarmMsg.setFaultCode(o.getFaultCode());
+                            LocalDateTime faultTime = DateUtil.Timestamp2LocalDateTime(o.getStartTime().getTime() + interval * 24 * 60 * 60 * 1000L);
+                            alarmMsg.setFaultTime(faultTime);
+                            alarmMsg.setFaultAdvice(o.getFaultAdvice());
+
+                            if (alarmMsg.getFaultLevel() <= 3) {
+                                alarmMsg.setFastCharge(BigDecimal.valueOf(random.nextInt(90)));
+                            } else {
+                                //数据类型)(最小值+Math.random()*(最大值-最小值+1)
+                                int r = (int) (90 + Math.random() * (100 - 90 + 1));
+                                alarmMsg.setFastCharge(BigDecimal.valueOf(r));
+                            }
+                            alarmMsg.setFaultStatus(0);
+                            alarmMsg.setSid(o.getId());
+                            alarmMsg.setType(1);
+                            if (alarmMsg.getFaultLevel() != null && alarmMsg.getFaultLevel() > 3) {
+                                alarmMsg.setUpdateBy(o.getUpdateBy());
+                            }
+                            alarmMsgList.add(alarmMsg);
+                        }
+                    });
+                    if (alarmMsgList.size() > 0) {
+                        alarmMsgList.forEach(o -> {
+                            alarmMsgWarnMapper.insert(o);
+                        });
+                    }
+                }
+            }
+
+            JSONObject baseData1 = JSONObject.parseObject(response.get(1));
+            List<AlarmMsgVo> alarmMsgVos1 = new ArrayList<>();
+            if (baseData1 != null && baseData1.get("data") != null) {
+                alarmMsgVos1 = JSONObject.parseArray(baseData1.get("data").toString(), AlarmMsgVo.class);
+                //确实存在报警信息
+                if (alarmMsgVos1.size() > 0) {
+                    Set<Long> sidSet = new HashSet<>();
+                    alarmMsgVos1.forEach(o -> {
+                        //flagSet.add(o.getSn() + o.getFaultCode() + o.getStartTime().getTime());
+                        sidSet.add(o.getId());
+                    });
+                    List<AlarmMsgWarn> list = alarmMsgWarnMapper.selectList(new LambdaQueryWrapper<AlarmMsgWarn>().eq(AlarmMsgWarn::getType, 2).in(AlarmMsgWarn::getSid, sidSet));
+                    List<AlarmMsgWarn> listFinal = new ArrayList<>();
+
+                    List<AlarmMsgWarn> alarmMsgList = new ArrayList<>();
+                    List<Model> models = modelMapper.selectList(new LambdaQueryWrapper<Model>().eq(Model::getIsDelete, 0));
+                    //sn号前
+                    alarmMsgVos1.forEach(o -> {
+                        //故障表是否已经存在
+                        AtomicBoolean had = new AtomicBoolean(false);
+                        if (sidSet.size() > 0) {
+                            if (sidSet.contains(o.getId())) {
+                                list.forEach(m -> {
+                                    if (m.getSid().equals(o.getId())) {
+                                        //发生和完结时间中包含当前时间的
+                                        LocalDateTime startTime = DateUtil.Timestamp2LocalDateTime(o.getStartTime().getTime() + interval * 24 * 60 * 60 * 1000L);
+                                        LocalDateTime finishTime = DateUtil.Timestamp2LocalDateTime(o.getEndTime().getTime() + interval * 24 * 60 * 60 * 1000L);
+                                        if (startTime.isBefore(LocalDateTime.now()) && finishTime.isAfter(LocalDateTime.now())) {
+                                            m.setFaultStatus(1);
+                                            m.setFinishTime(finishTime);
+                                            m.setType(2);
+                                            listFinal.add(m);
+                                            had.set(true);
+                                        }
+                                    }
+                                });
+                            }
+                        }
+                        if (!had.get()) {
+                            AlarmMsgWarn alarmMsg = new AlarmMsgWarn();
+                            if (models.size() > 0) {
+                                models.forEach(m -> {
+                                    if (m.getFaultCode().equals(o.getFaultCode())) {
+                                        alarmMsg.setFaultLevel(m.getFaultLevel());
+                                        alarmMsg.setFaultInfo(m.getAlgoName());
+                                    }
+                                });
+                            }
+                            alarmMsg.setSn(o.getSn());
+                            alarmMsg.setFaultCode(o.getFaultCode());
+                            LocalDateTime faultTime = DateUtil.Timestamp2LocalDateTime(o.getStartTime().getTime() + interval * 24 * 60 * 60 * 1000L);
+                            alarmMsg.setFaultTime(faultTime);
+                            alarmMsg.setFaultAdvice(o.getFaultAdvice());
+                            alarmMsg.setType(2);
+                            if (alarmMsg.getFaultLevel() <= 3) {
+                                alarmMsg.setFastCharge(BigDecimal.valueOf(random.nextInt(90)));
+                            } else {
+                                //数据类型)(最小值+Math.random()*(最大值-最小值+1)
+                                int r = (int) (90 + Math.random() * (100 - 90 + 1));
+                                alarmMsg.setFastCharge(BigDecimal.valueOf(r));
+                            }
+                            alarmMsg.setFaultStatus(0);
+                            LocalDateTime finishTime = DateUtil.Timestamp2LocalDateTime(o.getEndTime().getTime() + interval * 24 * 60 * 60 * 1000L);
+                            alarmMsg.setFinishTime(finishTime);
+                            if (alarmMsg.getFaultLevel() != null && alarmMsg.getFaultLevel() > 3) {
+                                alarmMsg.setUpdateBy(o.getUpdateBy());
+                            }
+                            alarmMsg.setSid(o.getId());
+                            alarmMsg.setId(null);
+                            alarmMsgList.add(alarmMsg);
+                        }
+                    });
+                    if (alarmMsgList.size() > 0) {
+                        this.saveBatch(alarmMsgList);
+                    }
+                    //更新状态
+                    if (listFinal.size() > 0) {
+                        this.updateBatchById(listFinal);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 故障信息
+     */
+    @Async
+    public Future<String> getBatteryMsg(String url, String paramJson) {
+        Map<String, String> mapHeaders = new HashMap<>();
+        mapHeaders.put("token", tokenSecret);
+        String response = okHttpCli.doPostTokenJson(url, paramJson, mapHeaders);
+        Future<String> result = new AsyncResult<>(response);
+        return result;
+    }
+
+    /**
+     * 各省比例
+     * @param province
+     * @return java.math.BigDecimal
+     */
+    private BigDecimal provinceRate(String province) {
+        long pro = deviceMapper.selectCount(new LambdaQueryWrapper<Device>().eq(Device::getProvince, province).eq(Device::getIsDelete, 0));
+        long total = deviceMapper.selectCount(new LambdaQueryWrapper<Device>().eq(Device::getIsDelete, 0));
+        return total > 0 ? BigDecimal.valueOf(pro).divide(BigDecimal.valueOf(total), 2, RoundingMode.HALF_UP) : BigDecimal.ZERO;
+    }
+
+}

+ 20 - 0
src/main/java/com/zhili/dashboard/service/impl/CommandServiceImpl.java

@@ -0,0 +1,20 @@
+package com.zhili.dashboard.service.impl;
+
+import com.zhili.dashboard.entity.Command;
+import com.zhili.dashboard.mapper.CommandMapper;
+import com.zhili.dashboard.service.ICommandService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 电池命令下发数据 服务实现类
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Service
+public class CommandServiceImpl extends ServiceImpl<CommandMapper, Command> implements ICommandService {
+
+}

+ 142 - 0
src/main/java/com/zhili/dashboard/service/impl/DeviceDurationServiceImpl.java

@@ -0,0 +1,142 @@
+package com.zhili.dashboard.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.zhili.dashboard.entity.Device;
+import com.zhili.dashboard.entity.DeviceDuration;
+import com.zhili.dashboard.mapper.DeviceDurationMapper;
+import com.zhili.dashboard.req.TableInfoParam;
+import com.zhili.dashboard.service.IDeviceDurationService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhili.dashboard.utils.OkHttpCli;
+import com.zhili.dashboard.vo.BatteryDataVo;
+import com.zhili.dashboard.vo.DeviceDurationVo;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.AsyncResult;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Future;
+
+/**
+ * <p>
+ * 电池状态统计信息 服务实现类
+ * </p>
+ *
+ * @author zyg
+ * @since 2022-07-05
+ */
+@Service
+public class DeviceDurationServiceImpl extends ServiceImpl<DeviceDurationMapper, DeviceDuration> implements IDeviceDurationService {
+
+    @Resource
+    OkHttpCli okHttpCli;
+
+    /**
+     * 数据获取地址
+     */
+    private static final String BATTERY_URL = "/admin/v1/hzBattery";
+    /**
+     * 故障信息地址
+     */
+    private static final String SIGNATURE = "AD5C4EC001352FFAC3A03CBA787A7417";
+
+    @Value("${openapi.token-secret}")
+    private String tokenSecret;
+    @Value("${openapi.url}")
+    private String openApiUrl;
+
+    /**
+     * 故障信息
+     */
+    @Async
+    public Future<String> getBatteryMsg(String url, String paramJson) {
+        Map<String, String> mapHeaders = new HashMap<>();
+        mapHeaders.put("token", tokenSecret);
+        String response = okHttpCli.doPostTokenJson(url, paramJson, mapHeaders);
+        Future<String> result = new AsyncResult<>(response);
+        return result;
+    }
+
+    /**
+     * 同步统计信息
+     */
+    @Override
+    public void syncDuration() {
+        QueryWrapper<DeviceDuration> queryWrapper = new QueryWrapper<>();
+        queryWrapper.select("max(sid) as id");
+        DeviceDuration duration = this.getOne(queryWrapper);
+
+        long maxId = 0L;
+        if (duration != null && duration.getId() != null) {
+            maxId = duration.getId();
+        }
+
+        //获取电池信息
+        List<String> response = new ArrayList<>();
+        try {
+            List<Future<String>> futures = new ArrayList<>();
+            TableInfoParam param = new TableInfoParam();
+            param.setSignature(SIGNATURE);
+            param.setInterfaceName("析锂时长");
+            param.setCondition("id>" + maxId);
+            param.setTableName("algo_lipltd_ai");
+            param.setFields("id,sn,cusum");
+
+            futures.add(getBatteryMsg(openApiUrl + BATTERY_URL, JSON.toJSONString(param)));
+            //死循环,每隔2000ms执行一次,判断一下这三个异步调用的方法是否全都执行完了。
+            while (true) {
+                //使用Future的isDone()方法返回该方法是否执行完成
+                if (futures.get(0).isDone()) {
+                    //如果异步方法全部执行完,跳出循环
+                    break;
+                }
+                //每隔200毫秒判断一次
+                Thread.sleep(200);
+            }
+            for (Future<String> future : futures) {
+                String string = future.get();
+                response.add(string);
+            }
+        } catch (Exception e) {
+            return;
+        }
+        // 故障信息解析
+        saveDuration(response);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    public void saveDuration(List<String> response) {
+        if (response.size() > 0) {
+            JSONObject baseData = JSONObject.parseObject(response.get(0));
+            List<DeviceDurationVo> deviceDurationVos = new ArrayList<>();
+            if (baseData != null && baseData.get("data") != null) {
+                deviceDurationVos = JSONObject.parseArray(baseData.get("data").toString(), DeviceDurationVo.class);
+                //确实存在报警信息
+                if (deviceDurationVos.size() > 0) {
+                    List<DeviceDuration> deviceList = new ArrayList<>();
+                    //sn号前
+                    deviceDurationVos.forEach(o -> {
+                        DeviceDuration device = new DeviceDuration();
+                        device.setSn(o.getSn());
+                        device.setDuration(new BigDecimal(o.getCusum()));
+                        device.setSid(o.getId());
+                        deviceList.add(device);
+                    });
+                    if (deviceList.size() > 0) {
+                        this.saveBatch(deviceList);
+                    }
+                }
+            }
+        }
+    }
+}

Some files were not shown because too many files changed in this diff