Browse Source

提交保存

soft5566 1 year ago
parent
commit
821e908bc8
56 changed files with 6141 additions and 0 deletions
  1. 23 0
      .gitignore
  2. 8 0
      .idea/.gitignore
  3. 6 0
      .idea/misc.xml
  4. 8 0
      .idea/modules.xml
  5. 6 0
      .idea/vcs.xml
  6. 9 0
      .idea/wanzai_video_kuayu.iml
  7. 2 0
      .mvn/wrapper/maven-wrapper.properties
  8. 316 0
      mvnw
  9. 188 0
      mvnw.cmd
  10. 142 0
      pom.xml
  11. 1177 0
      resources/sql/video.sql
  12. 13 0
      src/main/java/com/chuanghai/video/VideoTranscodingApplication.java
  13. 123 0
      src/main/java/com/chuanghai/video/common/Common.java
  14. 21 0
      src/main/java/com/chuanghai/video/config/WebMvcConfig.java
  15. 241 0
      src/main/java/com/chuanghai/video/controller/AdminController.java
  16. 696 0
      src/main/java/com/chuanghai/video/controller/CameraController.java
  17. 203 0
      src/main/java/com/chuanghai/video/controller/ConfigController.java
  18. 153 0
      src/main/java/com/chuanghai/video/controller/SpotController.java
  19. 794 0
      src/main/java/com/chuanghai/video/controller/VideoController.java
  20. 91 0
      src/main/java/com/chuanghai/video/core/ResponseResult.java
  21. 159 0
      src/main/java/com/chuanghai/video/core/ResponseStatus.java
  22. 79 0
      src/main/java/com/chuanghai/video/core/interceptor/JwtInterceptor.java
  23. 35 0
      src/main/java/com/chuanghai/video/entity/Admin.java
  24. 59 0
      src/main/java/com/chuanghai/video/entity/Camera.java
  25. 13 0
      src/main/java/com/chuanghai/video/entity/CameraRelationship.java
  26. 34 0
      src/main/java/com/chuanghai/video/entity/Config.java
  27. 23 0
      src/main/java/com/chuanghai/video/entity/Player.java
  28. 27 0
      src/main/java/com/chuanghai/video/entity/Spot.java
  29. 81 0
      src/main/java/com/chuanghai/video/mapper/AdminMapper.java
  30. 245 0
      src/main/java/com/chuanghai/video/mapper/CameraMapper.java
  31. 46 0
      src/main/java/com/chuanghai/video/mapper/ConfigMapper.java
  32. 65 0
      src/main/java/com/chuanghai/video/mapper/SpotMapper.java
  33. 116 0
      src/main/java/com/chuanghai/video/mapper/VideoMapper.java
  34. 28 0
      src/main/java/com/chuanghai/video/util/CommonUtil.java
  35. 87 0
      src/main/java/com/chuanghai/video/util/DateTimeUtil.java
  36. 62 0
      src/main/java/com/chuanghai/video/util/DbUtil.java
  37. 62 0
      src/main/java/com/chuanghai/video/util/JwtUtil.java
  38. 218 0
      src/main/java/com/chuanghai/video/util/OkHttpUtils.java
  39. 43 0
      src/main/java/com/chuanghai/video/util/PasswordEncryptionUtil.java
  40. 59 0
      src/main/resources/application.yml
  41. 83 0
      src/main/resources/sql/video.sql
  42. BIN
      src/main/resources/static/监控信息导入格式要求.xls
  43. 13 0
      src/test/java/com/chuanghai/video/VideoTranscodingApplicationTests.java
  44. 59 0
      target/classes/application.yml
  45. 83 0
      target/classes/sql/video.sql
  46. BIN
      target/classes/static/监控信息导入格式要求.xls
  47. 3 0
      target/maven-archiver/pom.properties
  48. 30 0
      target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
  49. 28 0
      target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
  50. 1 0
      target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst
  51. 1 0
      target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst
  52. 67 0
      target/surefire-reports/TEST-com.chuanghai.video.VideoTranscodingApplicationTests.xml
  53. 4 0
      target/surefire-reports/com.chuanghai.video.VideoTranscodingApplicationTests.txt
  54. BIN
      target/videoApi_wzsz.jar.original
  55. 8 0
      video_transcoding.iml
  56. BIN
      监控信息导入格式要求.xls

+ 23 - 0
.gitignore

@@ -0,0 +1,23 @@
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 6 - 0
.idea/misc.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectRootManager">
+    <output url="file://$PROJECT_DIR$/out" />
+  </component>
+</project>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/wanzai_video_kuayu.iml" filepath="$PROJECT_DIR$/.idea/wanzai_video_kuayu.iml" />
+    </modules>
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>

+ 9 - 0
.idea/wanzai_video_kuayu.iml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 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.6/apache-maven-3.8.6-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar

+ 316 - 0
mvnw

@@ -0,0 +1,316 @@
+#!/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%

+ 142 - 0
pom.xml

@@ -0,0 +1,142 @@
+<?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.8</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>com.chuanghai</groupId>
+    <artifactId>video_transcoding</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>video_transcoding</name>
+    <description>Demo project for Spring Boot</description>
+    <properties>
+        <java.version>1.8</java.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>0.9.1</version>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
+        <dependency>
+            <groupId>javax.xml.bind</groupId>
+            <artifactId>jaxb-api</artifactId>
+            <version>2.3.1</version>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.5.3</version>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
+        <dependency>
+            <groupId>com.alibaba.fastjson2</groupId>
+            <artifactId>fastjson2</artifactId>
+            <version>2.0.33</version>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter -->
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+            <version>1.4.7</version>
+        </dependency>
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>okhttp</artifactId>
+            <version>4.9.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <scope>runtime</scope>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>com.mysql</groupId>
+            <artifactId>mysql-connector-j</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <!-- Apache POI -->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+            <version>4.1.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>4.1.2</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>videoApi_wzsz</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <!-- 排除 doc 路径下的api文件 -->
+                        <exclude>**/doc/**</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+
+            <!-- smart doc -->
+            <plugin>
+                <groupId>com.github.shalousun</groupId>
+                <artifactId>smart-doc-maven-plugin</artifactId>
+                <version>2.2.2</version>
+                <configuration>
+                    <!--指定生成文档的使用的配置文件,配置文件放在自己的项目中-->
+                    <configFile>./src/main/resources/smart-doc.json</configFile>
+                    <!--指定项目名称-->
+                    <projectName>视频中台</projectName>
+                </configuration>
+                <executions>
+                    <execution>
+                        <!--如果不需要在执行编译时启动smart-doc,则将phase注释掉-->
+                        <phase>compile</phase>
+                        <goals>
+                            <!--smart-doc提供了html、openapi、markdown等goal,可按需配置-->
+                            <goal>html</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+        </plugins>
+
+    </build>
+
+</project>

File diff suppressed because it is too large
+ 1177 - 0
resources/sql/video.sql


+ 13 - 0
src/main/java/com/chuanghai/video/VideoTranscodingApplication.java

@@ -0,0 +1,13 @@
+package com.chuanghai.video;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class VideoTranscodingApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(VideoTranscodingApplication.class, args);
+    }
+
+}

+ 123 - 0
src/main/java/com/chuanghai/video/common/Common.java

@@ -0,0 +1,123 @@
+package com.chuanghai.video.common;
+
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.chuanghai.video.core.ResponseResult;
+import com.chuanghai.video.entity.Config;
+import com.chuanghai.video.mapper.VideoMapper;
+import com.chuanghai.video.util.OkHttpUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.List;
+
+
+@Component
+public class Common {
+
+    @Autowired
+    private VideoMapper videoMapper;
+
+    public ResponseResult getMediaList(@RequestBody String json) {
+        // 检测参数
+        if (json == null || json.isEmpty()) return ResponseResult.failed("请传参数!");
+
+        JSONObject urlObj = JSONObject.parseObject(json);
+        String stream = urlObj.getString("stream");
+        if (stream == null || stream.isEmpty())
+            return ResponseResult.failed("【stream】参数为空!");
+
+        String secret = "", vhost = "", port = "";
+        List<Config> return_config = videoMapper.getConfig();
+        if (return_config.size() > 0) {
+            for (Config cfg : return_config) {
+                // 拉流需要的秘钥
+                if ("api".equals(cfg.getCfgClass()) && "secret".equals(cfg.getCfgName())) {
+                    secret = cfg.getCfgValue();
+                }
+                // 拉流主机
+                if ("system".equals(cfg.getCfgClass()) && "vhost".equals(cfg.getCfgName())) {
+                    vhost = cfg.getCfgValue();
+                }
+                // 拉流主机端口
+                if ("system".equals(cfg.getCfgClass()) && "port".equals(cfg.getCfgName())) {
+                    port = cfg.getCfgValue();
+                }
+            }
+        }
+        if ("".equals(secret)) return ResponseResult.failed("配置表中没有配置秘钥:secret");
+        if ("".equals(vhost)) return ResponseResult.failed("配置表中没有配置主机:vhost");
+        if ("".equals(port)) return ResponseResult.failed("配置表中没有配置拉流主机端口:port");
+
+        try {
+            String base_uri = "http://" + vhost + ":" + port + "/index/api/getMediaList"
+                    + "?secret=" + secret
+                    + "&app=live"
+                    + "&stream=" + stream;
+            String local_uri = base_uri + "&vhost=__defaultVhost__";
+            // 发送http  get请求
+            OkHttpUtils okHttpUtils = new OkHttpUtils();
+            String s = okHttpUtils.get(local_uri);
+            JSONObject return_json = JSONObject.parse(s);
+
+            int code = return_json.getIntValue("code");
+            if (code == 0) {
+                JSONArray data = return_json.getJSONArray("data");
+                if (data == null) {
+                    String remote_uri = base_uri + "&vhost=" + vhost;
+                    // 发送http  get请求
+                    okHttpUtils = new OkHttpUtils();
+                    s = okHttpUtils.get(remote_uri);
+                    return_json = JSONObject.parse(s);
+                    code = return_json.getIntValue("code");
+                    if (code == 0) {
+                        data = return_json.getJSONArray("data");
+                        if (data == null) {
+                            // 视频流已经不存在,删除对应的记录
+                            int i = videoMapper.deleteByKey(stream);
+                            if (i > 0)
+                                return ResponseResult.success("本地、远程都不存在指定的流!更新数据表成功!");
+                            else
+                                return ResponseResult.success("本地、远程都不存在指定的流!更新数据表失败!");
+                        }
+
+                        if (data.size() > 0) {
+                            StringBuilder stringBuilder = new StringBuilder();
+                            int num = 0;
+                            for (int i = 0; i < data.size(); i++) {
+                                JSONObject jsonObject = data.getJSONObject(i);
+                                String schema = jsonObject.getString("schema");
+                                stringBuilder.append(schema).append(",");
+                                num++;
+                            }
+                            stringBuilder.setLength(stringBuilder.length() - 1);
+                            return ResponseResult.success("远程存在指定的流,有" + num + "协议:" + stringBuilder);
+                        } else {
+                            return ResponseResult.success("远程不存在指定的流");
+                        }
+                    } else {
+                        return ResponseResult.success(return_json);
+                    }
+                } else if (data.size() > 0) {
+                    StringBuilder stringBuilder = new StringBuilder();
+                    int num = 0;
+                    for (int i = 0; i < data.size(); i++) {
+                        JSONObject jsonObject = data.getJSONObject(i);
+                        String schema = jsonObject.getString("schema");
+                        stringBuilder.append(schema).append(",");
+                        num++;
+                    }
+                    stringBuilder.setLength(stringBuilder.length() - 1);
+                    return ResponseResult.success("本地存在指定的流,有" + num + "协议:" + stringBuilder);
+                } else {
+                    return ResponseResult.success("本地不存在指定的流");
+                }
+            } else {
+                return ResponseResult.success(return_json);
+            }
+        } catch (Exception e) {
+            return ResponseResult.failed("查询指定流异常:" + e.getMessage());
+        }
+    }
+}

+ 21 - 0
src/main/java/com/chuanghai/video/config/WebMvcConfig.java

@@ -0,0 +1,21 @@
+package com.chuanghai.video.config;
+
+import com.chuanghai.video.core.interceptor.JwtInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class WebMvcConfig implements WebMvcConfigurer {
+
+    @Autowired
+    private JwtInterceptor jwtInterceptor;
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        registry.addInterceptor(jwtInterceptor)
+                .addPathPatterns("/**")
+                .excludePathPatterns("/videoAdmin/login");
+    }
+}

+ 241 - 0
src/main/java/com/chuanghai/video/controller/AdminController.java

@@ -0,0 +1,241 @@
+package com.chuanghai.video.controller;
+
+import com.chuanghai.video.core.ResponseResult;
+import com.chuanghai.video.entity.Admin;
+import com.chuanghai.video.mapper.AdminMapper;
+import com.chuanghai.video.util.JwtUtil;
+import com.chuanghai.video.util.PasswordEncryptionUtil;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.sql.Timestamp;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/videoAdmin")
+public class AdminController {
+
+    @Autowired
+    private JwtUtil jwtUtil;
+
+    @Autowired
+    private AdminMapper adminMapper;
+
+    /**
+     * 登录
+     *
+     * @param admin 用户对象
+     * @return 返回响应
+     */
+    @PostMapping("/login")
+    public ResponseResult login(@RequestBody Admin admin) {
+        try {
+            String username = admin.getUsername();
+            String password = admin.getPassword();
+            if (username == null || password == null)
+                return ResponseResult.failed("【用户名】或【密码】为空!");
+
+            Admin u = new Admin();
+            u.setUsername(username);
+            List<Admin> login = adminMapper.login(u);
+            // 检验用户是否在数据库中
+            if (login.size() > 0) {
+                String s = encryption(password);
+
+                if (s.equals(login.get(0).getPassword())) {
+                    // 生成token
+                    String token = jwtUtil.generateToken(username);
+                    Map<String, String> strMap = new HashMap<>();
+                    strMap.put("token", token);
+
+                    return ResponseResult.success(strMap);
+                } else {
+                    return ResponseResult.failed("【用户名】或【密码】错误!");
+                }
+            } else {
+                return ResponseResult.failed("【用户名】或【密码】错误!");
+            }
+        } catch (Exception e) {
+            return ResponseResult.failed("登录失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 管理员用户分页列表,查询分页等
+     *
+     * @param pageNum   当前页
+     * @param pageSize  每页记录数
+     * @param name      姓名
+     * @param phone     手机
+     * @param adminType 用户类型
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     * @return 响应结果
+     */
+    @GetMapping("/list")
+    public ResponseResult list(@RequestParam(value = "pageNum", defaultValue = "1") int pageNum,
+                               @RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
+                               @RequestParam(value = "name", required = false) String name,
+                               @RequestParam(value = "phone", required = false) String phone,
+                               @RequestParam(value = "adminType", required = false) String adminType,
+                               @RequestParam(value = "startTime", required = false) Timestamp startTime,
+                               @RequestParam(value = "endTime", required = false) Timestamp endTime) {
+
+        if (pageSize < 1)
+            return ResponseResult.failed("每页显示记录数必须大于0!");
+
+        Admin admin = new Admin();
+        admin.setPageNum(pageNum);
+        admin.setPageSize(pageSize);
+        if (!"null".equals(name))
+            admin.setName(name);
+        if (!"null".equals(phone))
+            admin.setPhone(phone);
+        if (adminType != null)
+            admin.setAdminType(adminType);
+        if (startTime != null)
+            admin.setStartTime(startTime);
+        if (endTime != null)
+            admin.setEndTime(endTime);
+
+        try {
+            PageHelper.startPage(admin.getPageNum(), admin.getPageSize());
+            List<Admin> admins = adminMapper.list(admin);
+            PageInfo<Admin> adminPageInfo = new PageInfo<>(admins);
+
+            return ResponseResult.success(adminPageInfo);
+        } catch (Exception e) {
+            return ResponseResult.failed("列表失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 增加用户
+     *
+     * @param admin 用户对象
+     * @return 响应对象
+     */
+    @PostMapping("/add")
+    public ResponseResult add(@RequestBody Admin admin) {
+        try {
+            Boolean aBoolean = checkColumn(admin);
+            if (aBoolean)
+                return ResponseResult.failed("【用户名】、【密码】、【手机】和【用户类型】为空!");
+
+            List<Admin> admins = adminMapper.queryByUsernameOrPhone(admin);
+            if (admins.size() > 0)
+                return ResponseResult.failed("【用户名】或【手机】已被注册!");
+
+            admin.setPassword(encryption(admin.getPassword()));
+
+            int i = adminMapper.add(admin);
+            if (i == 1)
+                return ResponseResult.success("添加用户成功!");
+            else
+                return ResponseResult.failed("添加用户失败!");
+        } catch (Exception e) {
+            return ResponseResult.failed("添加用户失败:" + e.getMessage());
+        }
+    }
+
+    private Boolean checkColumn(Admin admin) {
+        String username = admin.getUsername();
+        String password = admin.getPassword();
+        String phone = admin.getPhone();
+        String adminType = admin.getAdminType();
+        return username == null || password == null || phone == null || adminType == null;
+    }
+
+    /**
+     * 修改用户
+     *
+     * @param admin 用户对象
+     * @return 响应对象
+     */
+    @PostMapping("/update")
+    public ResponseResult update(@RequestBody Admin admin) {
+        try {
+            Boolean aBoolean = checkColumn(admin);
+            if (aBoolean)
+                return ResponseResult.failed("【用户名】、【密码】、【手机】和【用户类型】为空!");
+
+            List<Admin> admins = adminMapper.queryByUsernameOrPhoneOrOthers(admin);
+            if (admins.size() > 0)
+                return ResponseResult.failed("用户未修改任何内容!");
+
+            admin.setPassword(encryption(admin.getPassword()));
+
+            int i = adminMapper.update(admin);
+            if (i == 1)
+                return ResponseResult.success("修改用户成功!");
+            else
+                return ResponseResult.failed("修改用户失败!");
+        } catch (Exception e) {
+            return ResponseResult.failed("修改用户失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 删除用户
+     *
+     * @param id 记录id
+     * @return 响应对象
+     */
+    @GetMapping("/delete")
+    public ResponseResult delete(@RequestParam(value = "id") String id) {
+        try {
+            if (id == null) {
+                return ResponseResult.failed("【id】为空!");
+            } else {
+                int i = adminMapper.delete(id);
+                if (i == 1)
+                    return ResponseResult.success("删除用户成功!");
+                else
+                    return ResponseResult.failed("可能没有对应的id,删除用户失败!");
+            }
+        } catch (Exception e) {
+            return ResponseResult.failed("删除用户失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 修改密码
+     *
+     * @param admin
+     * @return
+     */
+    @PostMapping("/updatePassword")
+    public ResponseResult updatePassword(@RequestBody Admin admin) {
+        try {
+            String id = admin.getId();
+            String password = admin.getPassword();
+            if (id == null || password == null)
+                return ResponseResult.failed("【id】或【密码】为空!");
+
+            // 加密处理
+            admin.setPassword(encryption(admin.getPassword()));
+
+            int i = adminMapper.update(admin);
+            if (i == 1)
+                return ResponseResult.success("修改密码成功!");
+            else
+                return ResponseResult.failed("修改密码失败!");
+        } catch (Exception e) {
+            return ResponseResult.failed("修改密码失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 加密
+     *
+     * @param password
+     * @return
+     */
+    private String encryption(String password) {
+        return PasswordEncryptionUtil.md5Hash(PasswordEncryptionUtil.sha2Hash(password));
+    }
+}

+ 696 - 0
src/main/java/com/chuanghai/video/controller/CameraController.java

@@ -0,0 +1,696 @@
+package com.chuanghai.video.controller;
+
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.chuanghai.video.core.ResponseResult;
+import com.chuanghai.video.entity.*;
+import com.chuanghai.video.mapper.CameraMapper;
+import com.chuanghai.video.mapper.VideoMapper;
+import com.chuanghai.video.util.JwtUtil;
+import com.chuanghai.video.util.OkHttpUtils;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLEncoder;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+
+@RestController
+@RequestMapping("/camera")
+public class CameraController {
+
+    @Autowired
+    private CameraMapper cameraMapper;
+
+    @Autowired
+    private VideoMapper videoMapper;
+
+    /**
+     * 监控信息列表
+     *
+     * @param camera 监控对象
+     * @return 响应对象
+     */
+    @GetMapping("/queryCamera")
+    public ResponseResult list(Camera camera) {
+        try {
+            // 检测参数
+            int pageNum, pageSize;
+            if (camera.getPageNum() != null && camera.getPageSize() != null && camera.getSpot() != null) {
+                pageNum = camera.getPageNum();
+                pageSize = camera.getPageSize();
+            } else {
+                return ResponseResult.failed("请输入【页码】、【每页记录数】、【景点名称】!");
+            }
+
+            String orderField = camera.getOrderField();
+            String order = camera.getOrder();
+            if (order != null && orderField == null) return ResponseResult.failed("请指定【排序字段】!");
+
+            PageHelper.startPage(pageNum, pageSize);
+            List<Camera> list = cameraMapper.list(camera);
+            PageInfo<Camera> cameras = new PageInfo<>(list);
+
+//            // 查询一下对应的流是否在线
+//            JSONObject jsonObject = new JSONObject();
+//            ResponseResult mediaList;
+//            String ipStr, streamId, ip;
+//            for (int i = 0; i < cameras.getList().size(); i++) {
+//                // ip
+//                if (cameras.getList().get(i).getIp() == null)
+//                    continue;
+//                ip = cameras.getList().get(i).getIp().replace(".", "");
+//                String nowLine = camera.getNowLine();
+//                ipStr = ip.substring(ip.length() - 6);
+//                // 流名称
+//                if (nowLine == null) {
+//                    streamId = "stream" + ipStr + "_2";
+//                } else {
+//                    streamId = "stream" + ipStr + "_" + nowLine;
+//                }
+
+//                jsonObject.put("stream", streamId);
+//                // 检测指定的流是否在线
+//                mediaList = this.getMediaList(jsonObject.toJSONString());
+//                if (!mediaList.getMsg().contains("协议")) {
+//                    cameras.getList().get(i).setVideoLinks(null);
+//                }
+//            }
+
+            return ResponseResult.success(cameras);
+        } catch (Exception e) {
+            return ResponseResult.failed("列表失败:" + e.getMessage());
+        }
+    }
+
+    @GetMapping("/queryCameraRelationship")
+    public ResponseResult listCameraRelationship() {
+        try {
+            List<CameraRelationship> list = cameraMapper.list_camera_relationship();
+            // 判断列表是否为空
+            if (list.isEmpty())
+                return ResponseResult.failed("列表为空");
+
+            List<String> save_key = new ArrayList<>();
+            List<Object> return_list = new ArrayList<>();
+            // 遍历列表
+            for (CameraRelationship cameraRelationship : list) {
+                String spotName = cameraRelationship.getSpotName();
+                if (!save_key.contains(spotName)) {
+                    save_key.add(spotName);
+                    List<Object> tmp_list = new ArrayList<>();
+                    for (CameraRelationship cr : list) {
+                        String sn = cr.getSpotName();
+                        if (sn.equals(spotName)) {
+                            String installationSite = cr.getInstallationSite();
+                            String channel = cr.getChannel();
+                            String d = cr.getD();
+                            // 定义返回map
+                            Map<String, String> tmpMap = new HashMap<>();
+                            tmpMap.put("installationSite", installationSite);
+                            tmpMap.put("channel", channel);
+                            tmpMap.put("d", d);
+                            // 添加到列表
+                            tmp_list.add(tmpMap);
+                        }
+                    }
+                    Map<String, Object> tmap = new HashMap<>();
+                    tmap.put("spotName", spotName);
+                    tmap.put("items", tmp_list);
+
+                    return_list.add(tmap);
+                }
+            }
+
+            return ResponseResult.success(return_list);
+        } catch (Exception e) {
+            return ResponseResult.failed("列表失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 查看是指定的流否在线
+     *
+     * @param json
+     * @return
+     */
+    private ResponseResult getMediaList(@RequestBody String json) {
+        // 检测参数
+        if (json == null || json.isEmpty()) return ResponseResult.failed("请传参数!");
+
+        JSONObject urlObj = JSONObject.parseObject(json);
+        String stream = urlObj.getString("stream");
+        if (stream == null || stream.isEmpty()) return ResponseResult.failed("【stream】参数为空!");
+
+        String secret = "", vhost = "", port = "";
+        List<Config> return_config = videoMapper.getConfig();
+        if (return_config.size() > 0) {
+            for (Config cfg : return_config) {
+                // 拉流需要的秘钥
+                if ("api".equals(cfg.getCfgClass()) && "secret".equals(cfg.getCfgName())) {
+                    secret = cfg.getCfgValue();
+                }
+                // 拉流主机
+                if ("system".equals(cfg.getCfgClass()) && "vhost".equals(cfg.getCfgName())) {
+                    vhost = cfg.getCfgValue();
+                }
+                // 拉流主机端口
+                if ("system".equals(cfg.getCfgClass()) && "port".equals(cfg.getCfgName())) {
+                    port = cfg.getCfgValue();
+                }
+            }
+        }
+        if ("".equals(secret)) return ResponseResult.failed("配置表中没有配置秘钥:secret");
+        if ("".equals(vhost)) return ResponseResult.failed("配置表中没有配置主机:vhost");
+        if ("".equals(port)) return ResponseResult.failed("配置表中没有配置拉流主机端口:port");
+
+        try {
+            String base_uri = "http://" + vhost + ":" + port + "/index/api/getMediaList" + "?secret=" + secret + "&app=live" + "&stream=" + stream;
+            String local_uri = base_uri + "&vhost=__defaultVhost__";
+            // 发送http  get请求
+            OkHttpUtils okHttpUtils = new OkHttpUtils();
+            String s = okHttpUtils.get(local_uri);
+            JSONObject return_json = JSONObject.parse(s);
+
+            int code = return_json.getIntValue("code");
+            if (code == 0) {
+                JSONArray data = return_json.getJSONArray("data");
+                if (data == null) {
+                    String remote_uri = base_uri + "&vhost=" + vhost;
+                    // 发送http  get请求
+                    okHttpUtils = new OkHttpUtils();
+                    s = okHttpUtils.get(remote_uri);
+                    return_json = JSONObject.parse(s);
+                    code = return_json.getIntValue("code");
+                    if (code == 0) {
+                        data = return_json.getJSONArray("data");
+                        if (data == null) {
+                            // 视频流已经不存在,删除对应的记录
+                            int i = videoMapper.deleteByKey(stream);
+                            if (i > 0) return ResponseResult.success("本地、远程都不存在指定的流!更新数据表成功!");
+                            else return ResponseResult.success("本地、远程都不存在指定的流!数据表不存在流信息!");
+                        }
+
+                        if (data.size() > 0) {
+                            StringBuilder stringBuilder = new StringBuilder();
+                            int num = 0;
+                            for (int i = 0; i < data.size(); i++) {
+                                JSONObject jsonObject = data.getJSONObject(i);
+                                String schema = jsonObject.getString("schema");
+                                stringBuilder.append(schema).append(",");
+                                num++;
+                            }
+                            stringBuilder.setLength(stringBuilder.length() - 1);
+                            return ResponseResult.success("远程存在指定的流,有" + num + "协议:" + stringBuilder);
+                        } else {
+                            return ResponseResult.success("远程不存在指定的流");
+                        }
+                    } else {
+                        return ResponseResult.success(return_json);
+                    }
+                } else if (data.size() > 0) {
+                    StringBuilder stringBuilder = new StringBuilder();
+                    int num = 0;
+                    for (int i = 0; i < data.size(); i++) {
+                        JSONObject jsonObject = data.getJSONObject(i);
+                        String schema = jsonObject.getString("schema");
+                        stringBuilder.append(schema).append(",");
+                        num++;
+                    }
+                    stringBuilder.setLength(stringBuilder.length() - 1);
+                    return ResponseResult.success("本地存在指定的流,有" + num + "协议:" + stringBuilder);
+                } else {
+                    return ResponseResult.success("本地不存在指定的流");
+                }
+            } else {
+                return ResponseResult.success(return_json);
+            }
+        } catch (Exception e) {
+            return ResponseResult.failed("查询指定流异常:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 监控信息列表, 安装位置 要求用正则表达式进行匹配
+     *
+     * @param camera 监控对象
+     * @return 响应对象
+     */
+    @PostMapping("/queryCameraByRegexp")
+    public ResponseResult listByRegexp(Camera camera) {
+        try {
+            int pageNum = camera.getPageNum();
+            int pageSize = camera.getPageSize();
+            if (pageSize < 1) return ResponseResult.failed("每页显示记录数必须大于0!");
+
+            String orderField = camera.getOrderField();
+            String order = camera.getOrder();
+            if (order != null && orderField == null) return ResponseResult.failed("请指定排序字段!");
+
+            String reg = camera.getRegularExpression();
+            if (reg == null || reg.isEmpty()) return ResponseResult.failed("【正则表达式】为空!");
+
+            PageHelper.startPage(pageNum, pageSize);
+            List<Camera> list = cameraMapper.listByRegexp(camera);
+            PageInfo<Camera> cameras = new PageInfo<>(list);
+
+            return ResponseResult.success(cameras);
+        } catch (Exception e) {
+            return ResponseResult.failed("列表失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 添加监控信息
+     *
+     * @param camera 监控对象
+     * @return 响应对象
+     */
+    @PostMapping("/addCamera")
+    public ResponseResult addCamera(@RequestBody Camera camera, HttpServletRequest request) {
+        try {
+            Object object = this.checkColumn(camera);
+            if (object instanceof ResponseResult) return (ResponseResult) object;
+
+            List<Camera> cameras = cameraMapper.queryByIpOrinstallationSite(camera);
+            if (cameras.size() > 0) return ResponseResult.failed("【安装位置】或【IP】或【频道】或【通道】经存在!");
+
+            List<Spot> spots = cameraMapper.querySpotIdBySpotName(camera.getSpot());
+            if (spots.size() == 0)
+                return ResponseResult.failed("【楼栋】不存在!请在【景点管理】中添加!");
+
+            int id = spots.get(0).getId();
+            camera.setSpot(String.valueOf(id));
+
+            // 获取Authorization头部
+            String authHeader = request.getHeader("admin_token");
+            // 假设token在Authorization头部,格式为 "prefix <token>"
+            if (authHeader != null && authHeader.startsWith("VIDEO")) {
+                JwtUtil jwtUtil = new JwtUtil();
+                String usernameFromToken = jwtUtil.getUsernameFromToken(authHeader.substring(5));
+                camera.setCreater(usernameFromToken);
+            }
+
+            int i = cameraMapper.add(camera);
+            if (i == 1) return ResponseResult.success("监控摄像头添加成功!");
+            else return ResponseResult.failed("监控摄像头添加失败!");
+        } catch (Exception e) {
+            return ResponseResult.failed("监控摄像头添加失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 检测字段是否合法
+     *
+     * @param camera
+     * @return
+     */
+    private Object checkColumn(Camera camera) {
+        String unitType = camera.getUnitType();
+        if (unitType == null) return ResponseResult.failed("【设备型号】为空!");
+
+        String vendor = camera.getVendor();
+        if (vendor == null) return ResponseResult.failed("【厂商】为空!");
+
+        String agreement = camera.getAgreement();
+        if (agreement == null) return ResponseResult.failed("【协议】为空!");
+
+        String installationSite = camera.getInstallationSite();
+        if (installationSite == null) return ResponseResult.failed("【安装位置】为空!");
+
+        String spot = camera.getSpot();
+        if (spot == null) return ResponseResult.failed("【景点名称】为空!");
+
+        String channel = camera.getChannel();
+        if (channel == null) return ResponseResult.failed("【频道】为空!");
+
+        String d = camera.getD();
+        if (d == null) return ResponseResult.failed("【通道】为空!");
+
+        String ip = camera.getIp();
+        if (ip == null) return ResponseResult.failed("【IP】为空!");
+
+        String ipPassword = camera.getIpPassword();
+        if (ipPassword == null) return ResponseResult.failed("【摄像头账号密码】为空!");
+
+//        String cameraCoding = camera.getCameraCoding();
+//        if (cameraCoding == null) return ResponseResult.failed("【摄像头编码】为空!");
+
+//        String creater = camera.getCreater();
+//        if (creater == null) return ResponseResult.failed("【创建人】为空!");
+
+        return true;
+    }
+
+    /**
+     * 修改监控信息
+     */
+    @PostMapping("/updateCamera")
+    public ResponseResult updateCamera(@RequestBody Camera camera, HttpServletRequest request) {
+        try {
+            Object object = this.checkColumn(camera);
+            if (object instanceof ResponseResult) return (ResponseResult) object;
+
+            List<Camera> cameras = cameraMapper.queryByIpOrinstallationSite(camera);
+            if (cameras.size() > 0)
+                return ResponseResult.failed("本记录数据未变更 或 【安装位置】或【IP】或【频道】或【通道】与其它记录重复!!");
+
+            List<Spot> spots = cameraMapper.querySpotIdBySpotName(camera.getSpot());
+            if (spots.size() == 0)
+                return ResponseResult.failed("【楼栋】不存在!请在【景点管理】中添加!");
+
+            int id = spots.get(0).getId();
+            camera.setSpot(String.valueOf(id));
+
+            // 获取Authorization头部
+            String authHeader = request.getHeader("admin_token");
+            // 假设token在Authorization头部,格式为 "prefix <token>"
+            if (authHeader != null && authHeader.startsWith("VIDEO")) {
+                JwtUtil jwtUtil = new JwtUtil();
+                String usernameFromToken = jwtUtil.getUsernameFromToken(authHeader.substring(5));
+                camera.setLastUpdater(usernameFromToken);
+            }
+
+            int i = cameraMapper.update(camera);
+            if (i == 1) return ResponseResult.success("监控摄像头修改成功!");
+            else return ResponseResult.failed("监控摄像头修改失败!");
+        } catch (Exception e) {
+            return ResponseResult.failed("监控摄像头修改失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 删除监控摄像头信息
+     *
+     * @param id 要删除的记录id
+     * @return 响应对象
+     */
+    @GetMapping("/delete")
+    public ResponseResult delete(String id) {
+        try {
+            if (id == null) {
+                return ResponseResult.failed("【id】为空!");
+            } else {
+                int i = cameraMapper.delete(id);
+                if (i == 1) return ResponseResult.success("删除监控摄像头成功!");
+                else return ResponseResult.failed("可能没有对应的id,删除监控摄像头失败!");
+            }
+        } catch (Exception e) {
+            return ResponseResult.failed("删除监控摄像头失败:" + e.getMessage());
+        }
+    }
+
+
+    /**
+     * 导出监控信息
+     *
+     * @param camera   请求数据
+     * @param response 响应数据
+     * @throws IOException IO异常
+     */
+    @PostMapping("/download")
+    public void exportToExcel(@RequestBody(required = false) Camera camera, HttpServletResponse response) throws IOException {
+        List<Camera> data;
+        if (camera == null) {
+            camera = new Camera();
+        }
+        // 从数据库获取数据
+        data = cameraMapper.list(camera);
+
+        // 创建工作簿和工作表
+        Workbook workbook = new XSSFWorkbook();
+        Sheet sheet = workbook.createSheet("监控信息表");
+
+        // 创建标题行,并设置样式
+        Row headerRow = sheet.createRow(0);
+        CellStyle headerCellStyle = workbook.createCellStyle();
+        headerCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
+        headerCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+        Font headerFont = workbook.createFont();
+        headerFont.setBold(true);
+        headerCellStyle.setFont(headerFont);
+
+        // 设置标题行的列名
+        String[] columnNames = {"id", "unitType", "vendor", "agreement", "installationSite", "ip", "ipPassword", "cameraCoding", "online", "statu", "remark", "creater", "createTime", "lastUpdater", "lastUpdateTime"};
+        for (int i = 0; i < columnNames.length; i++) {
+            Cell cell = headerRow.createCell(i);
+            cell.setCellValue(columnNames[i]);
+            cell.setCellStyle(headerCellStyle);
+        }
+
+        // 填充数据行,并设置样式
+        CellStyle dataCellStyle = workbook.createCellStyle();
+        dataCellStyle.setAlignment(HorizontalAlignment.CENTER); // 设置单元格居中对齐
+        dataCellStyle.setWrapText(false);
+        CreationHelper createHelper = workbook.getCreationHelper();
+        CellStyle dateCellStyle = workbook.createCellStyle();
+        dateCellStyle.cloneStyleFrom(dataCellStyle);
+        dateCellStyle.setDataFormat(createHelper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss")); // 设置日期时间格式
+
+        for (int i = 0; i < data.size(); i++) {
+            Row dataRow = sheet.createRow(i + 1);
+            Camera entity = data.get(i);
+            dataRow.createCell(0).setCellValue(i + 1);
+            dataRow.createCell(1).setCellValue(entity.getUnitType());
+            dataRow.createCell(2).setCellValue(entity.getVendor());
+            dataRow.createCell(3).setCellValue(entity.getAgreement());
+            dataRow.createCell(4).setCellValue(entity.getInstallationSite());
+            dataRow.createCell(5).setCellValue(entity.getIp());
+            dataRow.createCell(6).setCellValue(entity.getIpPassword());
+            dataRow.createCell(7).setCellValue(entity.getCameraCoding());
+            dataRow.createCell(8).setCellValue(entity.getOnline());
+            dataRow.createCell(9).setCellValue(entity.getStatu());
+            dataRow.createCell(10).setCellValue(entity.getRemark());
+            dataRow.createCell(11).setCellValue(entity.getCreater());
+
+            Cell createTimeCell = dataRow.createCell(12);
+            createTimeCell.setCellValue(entity.getCreateTime().toString().substring(0, entity.getCreateTime().toString().length() - 2));
+            createTimeCell.setCellStyle(dateCellStyle);
+
+            dataRow.createCell(13).setCellValue(entity.getLastUpdater());
+
+            Cell lastUpdateTimeCell = dataRow.createCell(14);
+            if (entity.getLastUpdateTime() == null) {
+                lastUpdateTimeCell.setCellValue((Date) null);
+            } else {
+                String tmpDate = entity.getLastUpdateTime().toString();
+                lastUpdateTimeCell.setCellValue(tmpDate.substring(0, tmpDate.length() - 2));
+            }
+            lastUpdateTimeCell.setCellStyle(dateCellStyle);
+
+            for (int j = 0; j < columnNames.length; j++) {
+                dataRow.getCell(j).setCellStyle(dataCellStyle);
+            }
+        }
+
+        // 自适应列宽
+        for (int i = 0; i < columnNames.length; i++) {
+            sheet.autoSizeColumn(i);
+        }
+
+        // 文件名
+        String filename = "监控信息_导出_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + ".xlsx";
+        String encodedFilename = URLEncoder.encode(filename, "UTF-8");
+        // 生成xlsx下载
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFilename + "\"");
+
+        workbook.write(response.getOutputStream());
+        workbook.close();
+    }
+
+
+    /**
+     * 时间格式转换方法,返回字符串类型
+     *
+     * @param val 解析到的时间字段值,类型:字符串 内容:Tue Aug 16 00:00:00 CST 2022
+     */
+    public String getDateOfString(String val) {
+        // 定义时间格式变量
+        SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        SimpleDateFormat dateFormat2 = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyy", Locale.US);
+        if (val != null) {//若表格数据存在时间字段空值,需要做判断,否则会报错
+            try {
+                Date date = dateFormat2.parse(val);//用国际化时间类型样式的字符串数据内容来解析转换为date类型 Tue Aug 16 00:00:00 CST 2022
+                return dateFormat1.format(date); //再将date类型变量按照业务原数据样式转换为字符串形式  2022-08-16 00:00:00
+            } catch (ParseException e) {
+                e.printStackTrace();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 导入监控信息
+     * 1.需要提示用户上传的excel文件需要符合规定的格式;
+     *
+     * @param file 需要导入的excel文件
+     * @return 响应对象
+     */
+    @PostMapping("/importByExcel")
+    public ResponseResult importExcel(@RequestParam("file") MultipartFile file) {
+        try {
+            // 执行开始时间
+            long startTime = System.currentTimeMillis();
+
+            String fileName = file.getOriginalFilename();
+            if (fileName != null && !fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {//判断文件格式
+                ResponseResult.failed("上传文件格式不正确");
+            }
+            boolean isExcel2003 = true;
+            if (fileName != null && fileName.matches("^.+\\.(?i)(xlsx)$")) {
+                isExcel2003 = false;
+            }
+
+            InputStream is = file.getInputStream(); //文件输入
+            Workbook workbook = null;
+            if (isExcel2003) {
+                workbook = new HSSFWorkbook(is);
+            } else {
+                workbook = new XSSFWorkbook(is);
+            }
+            // 响应对象中data
+            Map<String, Object> returnData = new HashMap<>();
+            returnData.put("importTotal", 0);
+            returnData.put("repetitionTotal", 0);
+            returnData.put("repetitionLineNumber", "");
+            returnData.put("installationSiteIsNullTotal", 0);
+            returnData.put("installationSiteIsNullLineNumber", "");
+            returnData.put("ipIsNullTotal", 0);
+            returnData.put("ipIsNullLineNumber", "");
+
+            // 重复的行号记录下来
+            StringBuilder repetitionLineNumber = new StringBuilder();
+            // 安装地址为空的记录下来
+            StringBuilder installationSiteIsNullLineNumber = new StringBuilder();
+            // ip为空的记录下来
+            StringBuilder ipIsNullLineNumber = new StringBuilder();
+
+            Sheet sheet = workbook.getSheetAt(0);
+            Iterator<Row> rows = sheet.iterator();
+            List<Camera> objects = new ArrayList<>();
+            // 记录行号
+            int line = -1;
+            while (rows.hasNext()) {
+                Row row = rows.next();
+                line = row.getRowNum();
+                if (line == 0) {
+                    // 跳过标题行
+                    continue;
+                }
+                // 判断【安装位置】、【IP】是否为空
+                if (row.getCell(4) == null) {
+                    returnData.put("installationSiteIsNullTotal", (int) returnData.get("installationSiteIsNullTotal") + 1);
+                    installationSiteIsNullLineNumber.append(line).append(",");
+                }
+                if (row.getCell(5) == null) {
+                    returnData.put("ipIsNullTotal", (int) returnData.get("ipIsNullTotal") + 1);
+                    ipIsNullLineNumber.append(line).append(",");
+                }
+
+                String position = row.getCell(4).getStringCellValue().trim();
+                String ip = row.getCell(5).getStringCellValue().trim();
+                // 创建对象赋值ip
+                Camera camera = new Camera();
+                camera.setIp(ip);
+                // 检查ip是否存在
+                List<Camera> cameras = cameraMapper.queryByIpOrinstallationSite(camera);
+                if (cameras.size() > 0) {
+                    returnData.put("repetitionTotal", (int) returnData.get("repetitionTotal") + 1);
+                    repetitionLineNumber.append(line).append(",");
+                    continue;
+                }
+
+
+                Camera object = new Camera();
+                if (row.getCell(1) == null) object.setUnitType(null);
+                else object.setUnitType(row.getCell(1).getStringCellValue().trim());
+
+                if (row.getCell(2) == null) object.setVendor(null);
+                else object.setVendor(row.getCell(2).getStringCellValue().trim());
+
+                if (row.getCell(3) == null) object.setAgreement(null);
+                else object.setAgreement(row.getCell(3).getStringCellValue().trim());
+
+                object.setInstallationSite(position);
+                object.setIp(ip);
+
+                if (row.getCell(6) == null) object.setIpPassword(null);
+                else object.setIpPassword(row.getCell(6).getStringCellValue().trim());
+
+                if (row.getCell(7) == null) object.setCameraCoding(null);
+                else object.setCameraCoding(row.getCell(7).getStringCellValue().trim());
+
+                if (row.getCell(8) == null) object.setOnline(null);
+                else object.setOnline(row.getCell(8).getStringCellValue().trim());
+
+                if (row.getCell(9) == null) object.setStatu(null);
+                else object.setStatu(row.getCell(9).getStringCellValue().trim());
+
+                if (row.getCell(10) == null) object.setRemark(null);
+                else object.setRemark(row.getCell(10).getStringCellValue().trim());
+
+                if (row.getCell(11) == null) object.setCreater(null);
+                else object.setCreater(row.getCell(11).getStringCellValue().trim());
+
+                if (row.getCell(13) == null) object.setLastUpdater(null);
+                else object.setLastUpdater(row.getCell(13).getStringCellValue());
+
+                objects.add(object);
+            }
+
+            // 将重复的行号赋值到map对应的字段中
+            if (repetitionLineNumber.length() > 0)
+                returnData.put("repetitionLineNumber", repetitionLineNumber.deleteCharAt(repetitionLineNumber.length() - 1));
+            if (installationSiteIsNullLineNumber.length() > 0)
+                returnData.put("installationSiteIsNullLineNumber", installationSiteIsNullLineNumber.deleteCharAt(installationSiteIsNullLineNumber.length() - 1));
+            if (ipIsNullLineNumber.length() > 0)
+                returnData.put("ipIsNullLineNumber", ipIsNullLineNumber.deleteCharAt(ipIsNullLineNumber.length() - 1));
+            // 保存到数据库中
+            for (Camera object : objects) {
+                int i = cameraMapper.importExcelToTable(object);
+                returnData.put("importTotal", (int) returnData.get("importTotal") + i);
+            }
+            // 执行结束时间
+            long endTime = System.currentTimeMillis();
+            long executionTime = endTime - startTime;
+            long milliseconds = executionTime % 1000;
+            long seconds = (executionTime / 1000) % 60;
+            long minutes = (executionTime / (1000 * 60)) % 60;
+            long hours = (executionTime / (1000 * 60 * 60)) % 24;
+
+            returnData.put("executionTime", hours + ":" + minutes + ":" + seconds + ":" + milliseconds);
+            return ResponseResult.success("导入成功!", returnData);
+        } catch (IOException e) {
+            return ResponseResult.failed("错误的文件:" + e.getMessage());
+        }
+    }
+
+    @GetMapping("/downloadTemp")
+    public void reactionDownload(HttpServletResponse response) throws Exception {
+        String path = "static/监控信息导入格式要求.xls"; // 后端中对应的excel文件目录
+        response.setContentType("application/vnd.ms-excel; charset=utf-8");
+        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("监控信息导入格式要求.xls", "UTF-8"));
+        ClassPathResource resource = new ClassPathResource(path);
+        InputStream input = resource.getInputStream();
+        byte[] data = new byte[1024];
+        int len;
+        while ((len = input.read(data)) != -1) {
+            response.getOutputStream().write(data, 0, len);
+        }
+    }
+}

+ 203 - 0
src/main/java/com/chuanghai/video/controller/ConfigController.java

@@ -0,0 +1,203 @@
+package com.chuanghai.video.controller;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.chuanghai.video.core.ResponseResult;
+import com.chuanghai.video.entity.Config;
+import com.chuanghai.video.mapper.ConfigMapper;
+import com.chuanghai.video.mapper.VideoMapper;
+import com.chuanghai.video.util.OkHttpUtils;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/config")
+public class ConfigController {
+
+    @Autowired
+    private VideoMapper videoMapper;
+
+    @Autowired
+    private ConfigMapper configMapper;
+
+    /**
+     * 重启拉流服务程序
+     */
+    @GetMapping("/restartServer")
+    public ResponseResult restartServer() {
+
+        String secret_table = "", vhost = "", port = "";
+        List<Config> return_config = videoMapper.getConfig();
+        if (return_config.size() == 0) {
+            return ResponseResult.failed("配置表中没有数据,请与管理员进行联系!");
+        } else {
+            for (Config cfg : return_config) {
+                // 拉流需要的秘钥
+                if ("api".equals(cfg.getCfgClass()) && "secret".equals(cfg.getCfgName())) {
+                    secret_table = cfg.getCfgValue();
+                }
+                // 拉流主机
+                if ("system".equals(cfg.getCfgClass()) && "vhost".equals(cfg.getCfgName())) {
+                    vhost = cfg.getCfgValue();
+                }
+                // 拉流主机端口
+                if ("system".equals(cfg.getCfgClass()) && "port".equals(cfg.getCfgName())) {
+                    port = cfg.getCfgValue();
+                }
+            }
+        }
+        if ("".equals(secret_table)) return ResponseResult.failed("配置表中没有配置秘钥:secret");
+        if ("".equals(vhost)) return ResponseResult.failed("配置表中没有配置主机:vhost");
+        if ("".equals(port)) return ResponseResult.failed("配置表中没有配置拉流主机端口:port");
+
+        try {
+            // 拉流接口
+            String uri = "http://" + vhost + ":" + port + "/index/api/restartServer" + "?secret=" + secret_table;
+
+            // 发送http  get请求
+            OkHttpUtils okHttpUtils = new OkHttpUtils();
+            String s = okHttpUtils.get(uri);
+            JSONObject return_json = JSONObject.parse(s);
+
+            int code = return_json.getIntValue("code");
+            if (code == 0) {
+                // 返回的提示信息
+                String msg = return_json.getString("msg");
+                if (msg.contains("秒后自动重启") || msg.contains("MediaServer will reboot in on")) return ResponseResult.success(msg);
+
+                return ResponseResult.failed("重启拉流服务失败!");
+            } else {
+                return ResponseResult.failed("重启拉流服务失败!");
+            }
+        } catch (Exception e) {
+            return ResponseResult.failed("重启拉流服务异常:" + e.getMessage());
+        }
+    }
+
+
+    @GetMapping("/setServerConfig")
+    public ResponseResult setServerConfig(@RequestParam Map<String, String> parameters) {
+        if (parameters.size() == 0) {
+            return ResponseResult.failed("每次至少修改1项配置");
+        } else if (parameters.size() > 1) {
+            return ResponseResult.failed("每次只能修改1项配置");
+        }
+
+        String paramName = "", paramValue = "";
+        for (Map.Entry<String, String> entry : parameters.entrySet()) {
+            paramName = entry.getKey();
+            paramValue = entry.getValue();
+            break;
+        }
+
+        // 判断客户端的参数是否为空
+        if (paramName.isEmpty() || paramValue.isEmpty())
+            return ResponseResult.failed("【配置名称】或【配置的值】为空!");
+
+        String secret = "", vhost = "", port = "";
+        boolean configName = false;
+        List<Config> return_config = videoMapper.getConfig();
+        if (return_config.size() == 0) {
+            return ResponseResult.failed("配置表中没有数据,请与管理员进行联系!");
+        } else {
+            for (Config cfg : return_config) {
+                // 拉流需要的秘钥
+                if ("api".equals(cfg.getCfgClass()) && "secret".equals(cfg.getCfgName())) {
+                    secret = cfg.getCfgValue();
+                    if ("".equals(secret))
+                        return ResponseResult.failed("配置表中没有配置秘钥:secret");
+                }
+                // 拉流主机
+                if ("system".equals(cfg.getCfgClass()) && "vhost".equals(cfg.getCfgName())) {
+                    vhost = cfg.getCfgValue();
+                    if ("".equals(vhost))
+                        return ResponseResult.failed("配置表中没有配置主机:vhost");
+                }
+                // 拉流主机端口
+                if ("system".equals(cfg.getCfgClass()) && "port".equals(cfg.getCfgName())) {
+                    port = cfg.getCfgValue();
+                    if ("".equals(port))
+                        return ResponseResult.failed("配置表中没有配置拉流主机端口:port");
+                }
+                if ((cfg.getCfgClass() + "." + cfg.getCfgName()).equals(paramName)) {
+                    configName = true;
+                    if ("0".equals(cfg.getAllowUpdate())) {
+                        return ResponseResult.failed("此配置项暂未开放修改");
+                    }
+                }
+            }
+        }
+
+        if (!configName)
+            return ResponseResult.failed("配置表中没有该配置项!");
+
+        try {
+            // 拉流接口
+            String uri = "http://" + vhost + ":" + port + "/index/api/setServerConfig"
+                    + "?secret=" + secret + "&" + paramName + "=" + paramValue;
+
+            // 发送http  get请求
+            OkHttpUtils okHttpUtils = new OkHttpUtils();
+            String s = okHttpUtils.get(uri);
+            JSONObject return_json = JSONObject.parse(s);
+
+            int code = return_json.getIntValue("code");
+            if (code == 0) {
+                // 配置项变更个数
+                int changed = Integer.parseInt(return_json.getString("changed"));
+                if (changed > 0) {
+                    Config config = new Config();
+                    config.setCfgClass(paramName.split("\\.")[0]);
+                    config.setCfgName(paramName.split("\\.")[1]);
+                    config.setCfgValue(paramValue);
+                    int i = configMapper.updateConfig(config);
+                    if (i == 1)
+                        return ResponseResult.success("配置文件修改成功!配置表修改成功!");
+                    else
+                        return ResponseResult.success("配置文件修改成功!配置表修改失败!");
+                } else {
+                    return ResponseResult.failed("配置无需修改,配置修改失败!");
+                }
+            } else {
+                return ResponseResult.failed("配置无需修改,配置修改失败!");
+            }
+        } catch (Exception e) {
+            return ResponseResult.failed("配置修改异常:" + e.getMessage());
+        }
+    }
+
+    @GetMapping("/showCfg")
+    public ResponseResult showConfig(Config config) {
+        // 检测参数
+        int pageNum, pageSize;
+        if (config.getPageNum() != null && config.getPageSize() != null) {
+            pageNum = config.getPageNum();
+            pageSize = config.getPageSize();
+        } else {
+            return ResponseResult.failed("请输入【页码】 或 【每页记录数】!");
+        }
+
+        if (config.getCfgValue() != null) {
+            if (config.getCfgClass() == null && config.getCfgName() == null)
+                return ResponseResult.failed("【配置类别】和【配置名称】都不能为空");
+        }
+
+        try {
+            PageHelper.startPage(pageNum, pageSize);
+            List<Config> list = configMapper.listConfig(config);
+            PageInfo<Config> configs = new PageInfo<>(list);
+
+            return ResponseResult.success(configs);
+        } catch (Exception e) {
+            return ResponseResult.failed("获取配置信息异常:" + e.getMessage());
+        }
+    }
+
+}

+ 153 - 0
src/main/java/com/chuanghai/video/controller/SpotController.java

@@ -0,0 +1,153 @@
+package com.chuanghai.video.controller;
+
+import com.chuanghai.video.core.ResponseResult;
+import com.chuanghai.video.entity.Spot;
+import com.chuanghai.video.mapper.SpotMapper;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.sql.Timestamp;
+import java.util.List;
+
+@RestController
+@RequestMapping("/videoSpot")
+public class SpotController {
+
+    @Autowired
+    private SpotMapper spotMapper;
+
+    /**
+     * 景点分页列表,查询分页等
+     * @param pageNum 页码
+     * @param pageSize 每页显示条数
+     * @param spotName 景点名称
+     * @param nvrIp 景点nvr的ip
+     * @param ipPassword nvr的账号密码
+     * @param startTime 开始时间
+     * @param endTime 结束时间
+     * @return 返回分页列表
+     */
+    @GetMapping("/list")
+    public ResponseResult list(@RequestParam(value = "pageNum", defaultValue = "1") int pageNum,
+                               @RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
+                               @RequestParam(value = "spotName", required = false) String spotName,
+                               @RequestParam(value = "nvrIp", required = false) String nvrIp,
+                               @RequestParam(value = "ipPassword", required = false) String ipPassword,
+                               @RequestParam(value = "startTime", required = false) Timestamp startTime,
+                               @RequestParam(value = "endTime", required = false) Timestamp endTime) {
+
+        if (pageSize < 1)
+            return ResponseResult.failed("每页显示记录数必须大于0!");
+
+        Spot spot = new Spot();
+        spot.setPageNum(pageNum);
+        spot.setPageSize(pageSize);
+        if (spotName != null)
+            spot.setSpotName(spotName);
+        if (nvrIp != null)
+            spot.setNvrIp(nvrIp);
+        if (ipPassword != null)
+            spot.setIpPassword(ipPassword);
+        if (startTime != null)
+            spot.setStartTime(startTime);
+        if (endTime != null)
+            spot.setEndTime(endTime);
+
+        try {
+            PageHelper.startPage(spot.getPageNum(), spot.getPageSize());
+            List<Spot> spots = spotMapper.list(spot);
+            PageInfo<Spot> spotPageInfo = new PageInfo<>(spots);
+
+            return ResponseResult.success(spotPageInfo);
+        } catch (Exception e) {
+            return ResponseResult.failed("列表失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 增加景点
+     *
+     * @param spot 景点对象
+     * @return 响应对象
+     */
+    @PostMapping("/add")
+    public ResponseResult add(@RequestBody Spot spot) {
+        try {
+            Boolean aBoolean = checkColumn(spot);
+            if (aBoolean)
+                return ResponseResult.failed("【景点名称】、【nvr的ip】或【nvr的账号密码】为空!");
+
+            List<Spot> spots = spotMapper.queryBySpotNameOrNvrIp(spot);
+            if (spots.size() > 0)
+                return ResponseResult.failed("【景点名称】或【nvr的ip】已存在!");
+
+            int i = spotMapper.add(spot);
+            if (i == 1)
+                return ResponseResult.success("添加【楼栋】成功!");
+            else
+                return ResponseResult.failed("添加【楼栋】失败!");
+        } catch (Exception e) {
+            return ResponseResult.failed("添加【楼栋】失败:" + e.getMessage());
+        }
+    }
+
+    private Boolean checkColumn(Spot spot) {
+        String spotName = spot.getSpotName();
+        String nvrIp = spot.getNvrIp();
+        String ipPassword = spot.getIpPassword();
+        return spotName == null || nvrIp == null || ipPassword == null;
+    }
+
+    /**
+     * 修改景点
+     *
+     * @param spot 景点对象
+     * @return 响应对象
+     */
+    @PostMapping("/update")
+    public ResponseResult update(@RequestBody Spot spot) {
+        try {
+            Boolean aBoolean = checkColumn(spot);
+            if (aBoolean)
+                return ResponseResult.failed("【景点名称】、【nvr的ip】或【nvr的账号密码】为空!");
+
+            List<Spot> spots = spotMapper.queryBySpotnameOrNvrIpOrOthers(spot);
+            if (spots.size() > 0)
+                return ResponseResult.failed("未修改任何内容!请修改后再提交!");
+
+            int i = spotMapper.update(spot);
+            if (i == 1)
+                return ResponseResult.success("修改【楼栋】成功!");
+            else
+                return ResponseResult.failed("修改【楼栋】失败!");
+        } catch (Exception e) {
+            return ResponseResult.failed("修改【楼栋】失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 删除景点
+     *
+     * @param id 景点id
+     * @return 响应对象
+     */
+    @GetMapping("/delete")
+    public ResponseResult delete(@RequestParam(value = "id") String id) {
+        try {
+            if (id == null) {
+                return ResponseResult.failed("【id】为空!");
+            } else {
+                int i = spotMapper.delete(id);
+                if (i == 1)
+                    return ResponseResult.success("删除【楼栋】成功!");
+                else
+                    return ResponseResult.failed("可能没有对应的id,删除【楼栋】失败!");
+            }
+        } catch (Exception e) {
+            return ResponseResult.failed("删除【楼栋】失败:" + e.getMessage());
+        }
+    }
+
+}

+ 794 - 0
src/main/java/com/chuanghai/video/controller/VideoController.java

@@ -0,0 +1,794 @@
+package com.chuanghai.video.controller;
+
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.chuanghai.video.core.ResponseResult;
+import com.chuanghai.video.entity.Camera;
+import com.chuanghai.video.entity.Config;
+import com.chuanghai.video.entity.Player;
+import com.chuanghai.video.entity.Spot;
+import com.chuanghai.video.mapper.CameraMapper;
+import com.chuanghai.video.mapper.VideoMapper;
+import com.chuanghai.video.util.OkHttpUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/stream")
+public class VideoController {
+
+    @Autowired
+    private CameraMapper cameraMapper;
+
+    @Autowired
+    private VideoMapper videoMapper;
+
+    /**
+     * 使用Stream推拉流
+     *
+     * @param camera 监控对象
+     * @return 响应对象
+     */
+    @PostMapping("/addStreamSource")
+    public ResponseResult requestAddStreamSource(@RequestBody Camera camera) {
+        // 检测参数
+        String d = camera.getD();
+        String tNowLine = camera.getNowLine();
+        if (d == null || tNowLine == null)
+            return ResponseResult.failed("【通道】或【当前线路】参数为空!");
+
+        List<Camera> list = cameraMapper.list(camera);
+        if (list.size() < 1)
+            return ResponseResult.failed("没有【通道】对应的监控!");
+
+        if (list.get(0).getChannel() == null || list.get(0).getChannel().equals(""))
+            return ResponseResult.failed("【频道】不存在!");
+
+        int nowLine = Integer.parseInt(tNowLine);
+        if (nowLine != 1 && nowLine != 2)
+            return ResponseResult.failed("【当前线路】只能为1或2!");
+
+        String vendor = list.get(0).getVendor();
+        String streamId = list.get(0).getChannel().toLowerCase() + "_" + nowLine;
+
+        String baseUrl = "", baseUrl_ws = "", secret = "", vhost = "", port = "";
+        String urlMp4, urlMp4_ws, urlFlv, urlFlv_ws, urlHls, urlTs, urlTs_ws;
+        StringBuilder videoLinks = new StringBuilder();
+        List<Config> return_config = videoMapper.getConfig();
+        Map<String, String> map = new HashMap<>();
+        if (return_config.size() > 0) {
+            for (Config cfg : return_config) {
+                // 监控视频拉流的基础url:baseUrl
+                if ("system".equals(cfg.getCfgClass()) && "baseUrl".equals(cfg.getCfgName())) {
+                    baseUrl = cfg.getCfgValue();
+                }
+                // 拉流需要的秘钥
+                if ("api".equals(cfg.getCfgClass()) && "secret".equals(cfg.getCfgName())) {
+                    secret = cfg.getCfgValue();
+                }
+                // 拉流主机
+                if ("system".equals(cfg.getCfgClass()) && "vhost".equals(cfg.getCfgName())) {
+                    vhost = cfg.getCfgValue();
+                }
+                // 拉流主机端口
+                if ("system".equals(cfg.getCfgClass()) && "port".equals(cfg.getCfgName())) {
+                    port = cfg.getCfgValue();
+                }
+
+                if ("protocol".equals(cfg.getCfgClass()) && "enable_hls".equals(cfg.getCfgName())) {
+                    if ("1".equals(cfg.getCfgValue())) {
+                        urlHls = "/live/" + streamId + "/hls.m3u8";
+                        map.put("hls", urlHls);
+                    }
+                }
+                // 是否开启转换为rtmp/flv
+                if ("protocol".equals(cfg.getCfgClass()) && "enable_rtmp".equals(cfg.getCfgName())) {
+                    if ("1".equals(cfg.getCfgValue())) {
+                        urlFlv = "/live/" + streamId + ".live.flv";
+                        urlFlv_ws = "/live/" + streamId + ".live.flv";
+                        map.put("flv", urlFlv);
+                        map.put("flv_ws", urlFlv_ws);
+                    }
+                }
+                // 是否开启转换为http-ts/ws-ts
+                if ("protocol".equals(cfg.getCfgClass()) && "enable_ts".equals(cfg.getCfgName())) {
+                    if ("1".equals(cfg.getCfgValue())) {
+                        urlTs = "/live/" + streamId + ".live.ts";
+                        urlTs_ws = "/live/" + streamId + ".live.ts";
+                        map.put("ts", urlTs);
+                        map.put("ts_ws", urlTs_ws);
+                    }
+                }
+                // 是否开启转换为http-fmp4/ws-fmp4
+                if ("protocol".equals(cfg.getCfgClass()) && "enable_fmp4".equals(cfg.getCfgName())) {
+                    if ("1".equals(cfg.getCfgValue())) {
+                        urlMp4 = "/live/" + streamId + ".live.mp4";
+                        urlMp4_ws = "/live/" + streamId + ".live.mp4";
+                        map.put("mp4", urlMp4);
+                        map.put("mp4_ws", urlMp4_ws);
+                    }
+                }
+            }
+
+            // 是否开启转换为hls(mpegts)
+            if (baseUrl == null || "".equals(baseUrl.trim())) {
+                baseUrl = "http://" + vhost + ":" + port;
+                baseUrl_ws = "ws://" + vhost + ":" + port;
+            } else {
+                if (baseUrl.startsWith("https")) {
+                    baseUrl_ws = "wss://" + baseUrl.substring(8);
+                } else {
+                    baseUrl_ws = "ws://" + baseUrl.substring(8);
+                }
+            }
+
+            // 遍历map,并根据条件更新每个值
+            for (Map.Entry<String, String> entry : map.entrySet()) {
+                String key = entry.getKey();
+                String newValue;
+                if (key.contains("ws")) {
+                    newValue = baseUrl_ws + entry.getValue();
+                } else {
+                    newValue = baseUrl + entry.getValue();
+                }
+                entry.setValue(newValue);
+                videoLinks.append(key).append(":").append(newValue).append(",");
+            }
+        }
+
+        if (!"".contentEquals(videoLinks)) {
+            videoLinks.setLength(videoLinks.length() - 1);
+            //map.put("videoLinks", videoLinks);
+        }
+
+        // 获取nvr的ip和账号密码
+        int spot = Integer.parseInt(list.get(0).getSpot());
+        List<Spot> return_spot = cameraMapper.getSpotInfo(spot);
+        String nvr_ip = return_spot.get(0).getNvrIp();
+        // 监控账号密码
+        String ipPassword = return_spot.get(0).getIpPassword();
+
+//        if ("".equals(baseUrl)) return ResponseResult.failed("配置表中没有配置基础URL:baseUrl");
+        if ("".equals(secret)) return ResponseResult.failed("配置表中没有配置秘钥:secret");
+        if ("".equals(vhost)) return ResponseResult.failed("配置表中没有配置主机:vhost");
+        if ("".equals(nvr_ip)) return ResponseResult.failed("配置表中没有配置nvr主机:nvr_ip");
+        if ("".equals(port)) return ResponseResult.failed("配置表中没有配置拉流主机端口:port");
+
+        //视频推拉流服务
+        String url;
+        if ("华为".equals(vendor)) {
+            url = "rtsp://" + ipPassword + "@" + nvr_ip + "/LiveMedia/ch1/Media" + nowLine;
+        } else {
+            url = "rtsp://" + ipPassword + "@" + nvr_ip + "/Streaming/Channels/" + list.get(0).getChannel().substring(1) +
+                    "0" + nowLine + "?transportmode=unicast";
+        }
+
+        try {
+            // 拉流接口
+            String uri = "http://" + vhost + ":" + port + "/index/api/addStreamProxy"
+                    + "?secret=" + secret
+                    + "&vhost=" + vhost
+                    + "&app=live"
+                    + "&stream=" + streamId
+                    + "&enable_audio=1"
+                    + "&add_mute_audio=1"
+                    + "&url=" + url;
+
+            // 发送http  get请求
+            OkHttpUtils okHttpUtils = new OkHttpUtils();
+            String s = okHttpUtils.get(uri);
+            JSONObject return_json = JSONObject.parse(s);
+            // System.out.println(return_json);
+
+            int code = return_json.getIntValue("code");
+            if (code == 0) {
+                JSONObject data = return_json.getJSONObject("data");
+                // 推流成功产生的唯一key
+                String key = data.getString("key");
+
+                // 保存ip:ip
+                // 推流成功产生的唯一key:key
+                // 线路:nowLine
+                // 如果之前有拉流,则更新:playerCount + 1,否则之间插入:playerCount
+                // 监控厂商:vendor
+                // 保存播放链接:videoLinks
+                Player player = new Player();
+                player.setIp(list.get(0).getIp());
+                player.setChannel(list.get(0).getChannel());
+                player.setD(list.get(0).getD());
+                player.setPlayerkey(key);
+                player.setVendor(list.get(0).getVendor());
+                player.setNowLine(String.valueOf(nowLine));
+                player.setVideoLinks(videoLinks.toString());
+
+                List<Player> players = videoMapper.queryPlayer(player);
+                if (players.size() > 0) {
+                    player.setId(players.get(0).getId());
+                    player.setPlayerCount(players.get(0).getPlayerCount() + 1);
+                    int i = videoMapper.updatePlayer(player);
+                    if (i == 1) {
+                        return ResponseResult.success("拉流成功,更新播放表成功!", map);
+                    } else {
+                        return ResponseResult.success("拉流成功,更新播放表失败!", map);
+                    }
+                } else {
+                    player.setPlayerCount(1);
+                    int i = videoMapper.add(player);
+                    if (i == 1) {
+                        return ResponseResult.success("拉流成功,插入播放表成功!", map);
+                    } else {
+                        return ResponseResult.success("拉流成功,插入播放表失败!", map);
+                    }
+                }
+            } else {
+                if ("This stream already exists".equals(return_json.getString("msg"))) {
+                    return ResponseResult.success("视频流已存在!", map);
+                } else {
+                    return ResponseResult.failed("拉流失败:" + return_json.getString("msg"));
+                }
+            }
+        } catch (Exception e) {
+            return ResponseResult.failed("拉流异常:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 关闭Stream推拉流
+     *
+     * @param player 传入player对象
+     * @return 响应对象
+     */
+    @PostMapping("/delStreamSource")
+    public ResponseResult requestDelStreamSource(@RequestBody Player player) {
+        // 检测参数
+        String d = player.getD();
+        String tNowLine = player.getNowLine();
+        if (d == null || tNowLine == null) return ResponseResult.failed("【通道】或【当前线路】参数为空!");
+
+        String secret = "", vhost = "", port = "";
+        List<Config> return_config = videoMapper.getConfig();
+        if (return_config.size() > 0) {
+            for (Config cfg : return_config) {
+                // 拉流需要的秘钥
+                if ("api".equals(cfg.getCfgClass()) && "secret".equals(cfg.getCfgName())) {
+                    secret = cfg.getCfgValue();
+                }
+                // 拉流主机
+                if ("system".equals(cfg.getCfgClass()) && "vhost".equals(cfg.getCfgName())) {
+                    vhost = cfg.getCfgValue();
+                }
+                // 拉流主机端口
+                if ("system".equals(cfg.getCfgClass()) && "port".equals(cfg.getCfgName())) {
+                    port = cfg.getCfgValue();
+                }
+            }
+        }
+        if ("".equals(secret)) return ResponseResult.failed("配置表中没有配置秘钥:secret");
+        if ("".equals(vhost)) return ResponseResult.failed("配置表中没有配置主机:vhost");
+        if ("".equals(port)) return ResponseResult.failed("配置表中没有配置拉流主机端口:port");
+
+        String key = "";
+        // 查询是否存在对应ip的流
+        List<Player> players = videoMapper.queryPlayer(player);
+        if (players.size() == 0) {
+            Camera camera = new Camera();
+            camera.setD(player.getD());
+            List<Camera> cameras = cameraMapper.queryChannel(camera);
+            key = vhost + "/live/" + cameras.get(0).getChannel() + "_" + tNowLine;
+        } else {
+            key = players.get(0).getPlayerkey();
+        }
+        int playerCount = players.get(0).getPlayerCount();
+
+        try {
+            String uri = "http://" + vhost + ":" + port + "/index/api/delStreamProxy"
+                    + "?secret=" + secret
+                    + "&key=" + key;
+            // 发送http  get请求
+            OkHttpUtils okHttpUtils = new OkHttpUtils();
+            String s = okHttpUtils.get(uri);
+            JSONObject return_json = JSONObject.parse(s);
+            // System.out.println(return_json);
+
+            int code = return_json.getIntValue("code");
+            if (code == 0) {
+                JSONObject data = return_json.getJSONObject("data");
+                // 成功与否
+                boolean flag = data.getBooleanValue("flag");
+                if (flag) {
+                    Player updatePlayer = new Player();
+                    updatePlayer.setId(players.get(0).getId());
+                    if (playerCount == 1) {
+                        // 删除
+                        int i = videoMapper.delete(String.valueOf(players.get(0).getId()));
+                        if (i > 0)
+                            return ResponseResult.success("关闭流成功,删除数据表成功!");
+                        else
+                            return ResponseResult.success("关闭流成功,删除数据表失败!");
+                    } else {
+                        updatePlayer.setPlayerCount(playerCount - 1);
+                        // 更新
+                        int i = videoMapper.updatePlayer(updatePlayer);
+                        if (i > 0)
+                            return ResponseResult.success("关闭流成功,更新数据表成功!");
+                        else
+                            return ResponseResult.success("关闭流成功,更新数据表失败!");
+                    }
+                } else {
+                    return ResponseResult.success("关闭流失败!视频流已经不存在!");
+                }
+            } else {
+                return ResponseResult.success("关闭流失败!code=" + code);
+            }
+        } catch (Exception e) {
+            return ResponseResult.failed("关闭流异常:" + e.getMessage());
+        }
+    }
+
+//    /**
+//     * 使用Stream推拉playback流
+//     *
+//     * @param rtsp_url
+//     * @return
+//     */
+//    @PostMapping("/addPbStreamSource")
+//    public ResponseResult requestAddPbStreamSource(@RequestBody String rtsp_url) {
+//        // 检测参数
+//        if (rtsp_url == null || rtsp_url.isEmpty())
+//            return ResponseResult.failed("请传参数!");
+//
+//        JSONObject urlObj = JSONObject.parseObject(rtsp_url);
+//        String url = urlObj.getString("url");
+//        if (url == null || url.isEmpty())
+//            return ResponseResult.failed("【rtsp_url】参数为空!");
+//
+//        String[] parts = url.split("/");
+//        String bValue = "";
+//        String eValue = "";
+//        int firstIndex = rtsp_url.indexOf('@');
+//        int secondIndex = rtsp_url.indexOf('@', firstIndex + 1);
+//        int colonIndex = rtsp_url.indexOf(':', secondIndex);
+//        String ip = rtsp_url.substring(secondIndex + 1, colonIndex);
+//
+//        for (int i = 0; i < parts.length; i++) {
+//            if (parts[i].startsWith("b")) {
+//                bValue = parts[i];
+//            } else if (parts[i].startsWith("e")) {
+//                eValue = parts[i];
+//            }
+//        }
+//
+//        Date bdate = new Date(Long.parseLong(bValue.substring(1)) * 1000L);
+//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+//        String formattedbDate = sdf.format(bdate);
+//        Date edate = new Date(Long.parseLong(eValue.substring(1)) * 1000L);
+//        String formattedeDate = sdf.format(edate);
+//
+//        String streamId = "pb" + formattedbDate.replaceAll("[- :]", "") + "_"
+//                + formattedeDate.replaceAll("[- :]", "");
+//
+//        String baseUrl = "", secret = "", vhost = "", port = "";
+//        String urlMp4, urlFlv, urlHls, urlTs;
+//        StringBuilder videoLinks = new StringBuilder();
+//        List<Config> return_config = videoMapper.getConfig();
+//        Map<String, String> map = new HashMap<>();
+//        if (return_config.size() > 0) {
+//            for (Config cfg : return_config) {
+//                // 监控视频拉流的基础url:baseUrl
+//                if ("system".equals(cfg.getCfgClass()) && "baseUrl".equals(cfg.getCfgName())) {
+//                    baseUrl = cfg.getCfgValue();
+//                }
+//                // 拉流需要的秘钥
+//                if ("api".equals(cfg.getCfgClass()) && "secret".equals(cfg.getCfgName())) {
+//                    secret = cfg.getCfgValue();
+//                }
+//                // 拉流主机
+//                if ("system".equals(cfg.getCfgClass()) && "vhost".equals(cfg.getCfgName())) {
+//                    vhost = cfg.getCfgValue();
+//                }
+//                // 拉流主机端口
+//                if ("system".equals(cfg.getCfgClass()) && "port".equals(cfg.getCfgName())) {
+//                    port = cfg.getCfgValue();
+//                }
+//                // 是否开启转换为hls(mpegts)
+//                if ("protocol".equals(cfg.getCfgClass()) && "enable_hls".equals(cfg.getCfgName())) {
+//                    if ("1".equals(cfg.getCfgValue())) {
+//                        urlHls = baseUrl + "/live/" + streamId + "/hls.m3u8";
+//                        videoLinks.append(urlHls).append(",");
+//                        map.put("hls", urlHls);
+//                    }
+//                }
+//                // 是否开启转换为rtmp/flv
+//                if ("protocol".equals(cfg.getCfgClass()) && "enable_rtmp".equals(cfg.getCfgName())) {
+//                    if ("1".equals(cfg.getCfgValue())) {
+//                        urlFlv = baseUrl + "/live/" + streamId + ".live.flv";
+//                        videoLinks.append(urlFlv).append(",");
+//                        map.put("flv", urlFlv);
+//                    }
+//                }
+//                // 是否开启转换为http-ts/ws-ts
+//                if ("protocol".equals(cfg.getCfgClass()) && "enable_ts".equals(cfg.getCfgName())) {
+//                    if ("1".equals(cfg.getCfgValue())) {
+//                        urlTs = baseUrl + "/link/live/" + streamId + ".live.ts";
+//                        videoLinks.append(urlTs).append(",");
+//                        map.put("ts", urlTs);
+//                    }
+//                }
+//                // 是否开启转换为http-fmp4/ws-fmp4
+//                if ("protocol".equals(cfg.getCfgClass()) && "enable_fmp4".equals(cfg.getCfgName())) {
+//                    if ("1".equals(cfg.getCfgValue())) {
+//                        urlMp4 = baseUrl + "/live/" + streamId + ".live.mp4";
+//                        videoLinks.append(urlMp4).append(",");
+//                        map.put("mp4", urlMp4);
+//                    }
+//                }
+//            }
+//        }
+//
+//        if (!"".contentEquals(videoLinks)) {
+//            videoLinks.setLength(videoLinks.length() - 1);
+//            //map.put("videoLinks", videoLinks);
+//        }
+//
+//        if ("".equals(baseUrl)) return ResponseResult.failed("配置表中没有配置基础URL:baseUrl");
+//        if ("".equals(secret)) return ResponseResult.failed("配置表中没有配置秘钥:secret");
+//        if ("".equals(vhost)) return ResponseResult.failed("配置表中没有配置主机:vhost");
+//        if ("".equals(port)) return ResponseResult.failed("配置表中没有配置拉流主机端口:port");
+//
+//        try {
+//            // 拉流接口
+//            String uri = "http://" + vhost + ":" + port + "/index/api/addStreamProxy"
+//                    + "?secret=" + secret
+//                    + "&vhost=" + vhost
+//                    + "&app=live"
+//                    + "&stream=" + streamId
+//                    + "&enable_audio=1"
+//                    + "&add_mute_audio=1"
+//                    + "&url=" + url;
+//            // 发送http  get请求
+//            OkHttpUtils okHttpUtils = new OkHttpUtils();
+//            String s = okHttpUtils.get(uri);
+//            JSONObject return_json = JSONObject.parse(s);
+//
+//            int code = return_json.getIntValue("code");
+//            if (code == 0) {
+//                JSONObject data = return_json.getJSONObject("data");
+//                // 推流成功产生的唯一key
+//                String key = data.getString("key");
+//
+//                // 保存ip:ip
+//                // 推流成功产生的唯一key:key
+//                // 线路:nowLine
+//                // 如果之前有拉流,则更新:playerCount + 1,否则之间插入:playerCount
+//                // 监控厂商:vendor
+//                // 保存播放链接:videoLinks
+//                Player player = new Player();
+//                player.setIp(ip);
+//                player.setPlayerkey(key);
+//                player.setVideoLinks(videoLinks.toString());
+//
+//                List<Player> players = videoMapper.queryPlayer(player);
+//                if (players.size() > 0) {
+//                    player.setId(players.get(0).getId());
+//                    player.setPlayerCount(players.get(0).getPlayerCount() + 1);
+//                    int i = videoMapper.updatePlayer(player);
+//                    if (i == 1) {
+//                        return ResponseResult.success("拉流成功+1!", map);
+//                    } else {
+//                        return ResponseResult.success("拉流成功,更新播放表失败!", map);
+//                    }
+//                } else {
+//                    player.setPlayerCount(1);
+//                    int i = videoMapper.add(player);
+//                    if (i == 1) {
+//                        return ResponseResult.success("拉流成功,插入播放表成功!", map);
+//                    } else {
+//                        return ResponseResult.success("拉流成功,插入播放表失败!", map);
+//                    }
+//                }
+//            } else {
+//                return ResponseResult.failed("拉流失败:" + return_json.getString("msg"));
+//            }
+//        } catch (Exception e) {
+//            return ResponseResult.failed("拉流异常:" + e.getMessage());
+//        }
+//    }
+
+//    /**
+//     * 关闭Stream推拉playback流
+//     *
+//     * @param json
+//     * @return
+//     */
+//    @PostMapping("/delPbStreamSource")
+//    public ResponseResult requestDelPbStreamSource(@RequestBody String json) {
+//        // 检测参数
+//        if (json == null || json.isEmpty()) return ResponseResult.failed("请传参数!");
+//
+//        JSONObject urlObj = JSONObject.parseObject(json);
+//        String paramkey = urlObj.getString("key");
+//        if (paramkey == null || paramkey.isEmpty())
+//            return ResponseResult.failed("【key】参数为空!");
+//
+//        Player player = new Player();
+//        player.setPlayerkey(paramkey);
+//
+//        // 查询是否存在对应ip的流
+//        List<Player> players = videoMapper.queryPlayer(player);
+//        if (players.size() < 1)
+//            return ResponseResult.failed("没有对应【IP】的视频流,或许已经关闭!");
+//
+//        String key = players.get(0).getPlayerkey();
+//        int playerCount = players.get(0).getPlayerCount();
+//
+//        String secret = "", vhost = "", port = "";
+//        List<Config> return_config = videoMapper.getConfig();
+//        if (return_config.size() > 0) {
+//            for (Config cfg : return_config) {
+//                // 拉流需要的秘钥
+//                if ("api".equals(cfg.getCfgClass()) && "secret".equals(cfg.getCfgName())) {
+//                    secret = cfg.getCfgValue();
+//                }
+//                // 拉流主机
+//                if ("system".equals(cfg.getCfgClass()) && "vhost".equals(cfg.getCfgName())) {
+//                    vhost = cfg.getCfgValue();
+//                }
+//                // 拉流主机端口
+//                if ("system".equals(cfg.getCfgClass()) && "port".equals(cfg.getCfgName())) {
+//                    port = cfg.getCfgValue();
+//                }
+//            }
+//        }
+//        if ("".equals(secret)) return ResponseResult.failed("配置表中没有配置秘钥:secret");
+//        if ("".equals(vhost)) return ResponseResult.failed("配置表中没有配置主机:vhost");
+//        if ("".equals(port)) return ResponseResult.failed("配置表中没有配置拉流主机端口:port");
+//
+//        try {
+//            String uri = "http://" + vhost + ":" + port + "/index/api/delStreamProxy"
+//                    + "?secret=" + secret
+//                    + "&key=" + key;
+//            // 发送http  get请求
+//            OkHttpUtils okHttpUtils = new OkHttpUtils();
+//            String s = okHttpUtils.get(uri);
+//            JSONObject return_json = JSONObject.parse(s);
+//
+//            int code = return_json.getIntValue("code");
+//            if (code == 0) {
+//                JSONObject data = return_json.getJSONObject("data");
+//                // 成功与否
+//                boolean flag = data.getBooleanValue("flag");
+//                if (flag) {
+//                    Player updatePlayer = new Player();
+//                    updatePlayer.setId(players.get(0).getId());
+//                    if (playerCount == 1) {
+//                        // 删除
+//                        int i = videoMapper.delete(String.valueOf(players.get(0).getId()));
+//                        if (i > 0)
+//                            return ResponseResult.success("关闭流成功-1,更新数据表成功!");
+//                        else
+//                            return ResponseResult.success("关闭流成功,数据表不存在流信息!");
+//                    } else {
+//                        updatePlayer.setPlayerCount(playerCount - 1);
+//                        // 更新
+//                        int i = videoMapper.updatePlayer(updatePlayer);
+//                        if (i > 0)
+//                            return ResponseResult.success("关闭流成功-1,更新数据表成功!");
+//                        else
+//                            return ResponseResult.success("关闭流成功,更新数据表失败!");
+//                    }
+//                } else {
+//                    // 视频流已经不存在,删除对应的记录
+//                    int i = videoMapper.deleteByKey(key);
+//                    if (i > 0)
+//                        return ResponseResult.success("关闭流失败!视频流已经不存在!更新数据表成功!");
+//                    else
+//                        return ResponseResult.success("关闭流失败!视频流已经不存在!更新数据表失败!");
+//                }
+//            } else {
+//                return ResponseResult.success("关闭流失败!code=" + code);
+//            }
+//        } catch (Exception e) {
+//            return ResponseResult.failed("关闭流异常:" + e.getMessage());
+//        }
+//    }
+
+    /**
+     * 指定的流是否在线
+     *
+     * @param json
+     * @return
+     */
+    @PostMapping("/isOnline")
+    public ResponseResult getMediaList(@RequestBody String json) {
+        // 检测参数
+        if (json == null || json.isEmpty()) return ResponseResult.failed("请传参数!");
+
+        JSONObject urlObj = JSONObject.parseObject(json);
+        String stream = urlObj.getString("stream");
+        if (stream == null || stream.isEmpty())
+            return ResponseResult.failed("【stream】参数为空!");
+
+        String secret = "", vhost = "", port = "";
+        List<Config> return_config = videoMapper.getConfig();
+        if (return_config.size() > 0) {
+            for (Config cfg : return_config) {
+                // 拉流需要的秘钥
+                if ("api".equals(cfg.getCfgClass()) && "secret".equals(cfg.getCfgName())) {
+                    secret = cfg.getCfgValue();
+                }
+                // 拉流主机
+                if ("system".equals(cfg.getCfgClass()) && "vhost".equals(cfg.getCfgName())) {
+                    vhost = cfg.getCfgValue();
+                }
+                // 拉流主机端口
+                if ("system".equals(cfg.getCfgClass()) && "port".equals(cfg.getCfgName())) {
+                    port = cfg.getCfgValue();
+                }
+            }
+        }
+        if ("".equals(secret)) return ResponseResult.failed("配置表中没有配置秘钥:secret");
+        if ("".equals(vhost)) return ResponseResult.failed("配置表中没有配置主机:vhost");
+        if ("".equals(port)) return ResponseResult.failed("配置表中没有配置拉流主机端口:port");
+
+        try {
+            String base_uri = "http://" + vhost + ":" + port + "/index/api/getMediaList"
+                    + "?secret=" + secret
+                    + "&app=live"
+                    + "&stream=" + stream;
+            String local_uri = base_uri + "&vhost=__defaultVhost__";
+            // 发送http  get请求
+            OkHttpUtils okHttpUtils = new OkHttpUtils();
+            String s = okHttpUtils.get(local_uri);
+            JSONObject return_json = JSONObject.parse(s);
+
+            int code = return_json.getIntValue("code");
+            if (code == 0) {
+                JSONArray data = return_json.getJSONArray("data");
+                if (data == null) {
+                    String remote_uri = base_uri + "&vhost=" + vhost;
+                    // 发送http  get请求
+                    okHttpUtils = new OkHttpUtils();
+                    s = okHttpUtils.get(remote_uri);
+                    return_json = JSONObject.parse(s);
+                    code = return_json.getIntValue("code");
+                    if (code == 0) {
+                        data = return_json.getJSONArray("data");
+                        if (data == null) {
+                            // 视频流已经不存在,删除对应的记录
+                            int i = videoMapper.deleteByKey(stream);
+                            if (i > 0)
+                                return ResponseResult.success("本地、远程都不存在指定的流!更新数据表成功!");
+                            else
+                                return ResponseResult.success("本地、远程都不存在指定的流!数据表不存在流信息!");
+                        }
+
+                        if (data.size() > 0) {
+                            StringBuilder stringBuilder = new StringBuilder();
+                            int num = 0;
+                            for (int i = 0; i < data.size(); i++) {
+                                JSONObject jsonObject = data.getJSONObject(i);
+                                String schema = jsonObject.getString("schema");
+                                stringBuilder.append(schema).append(",");
+                                num++;
+                            }
+                            stringBuilder.setLength(stringBuilder.length() - 1);
+                            return ResponseResult.success("远程存在指定的流,有" + num + "协议", stringBuilder);
+                        } else {
+                            return ResponseResult.success("远程不存在指定的流");
+                        }
+                    } else {
+                        return ResponseResult.success(return_json);
+                    }
+                } else if (data.size() > 0) {
+                    StringBuilder stringBuilder = new StringBuilder();
+                    int num = 0;
+                    for (int i = 0; i < data.size(); i++) {
+                        JSONObject jsonObject = data.getJSONObject(i);
+                        String schema = jsonObject.getString("schema");
+                        stringBuilder.append(schema).append(",");
+                        num++;
+                    }
+                    stringBuilder.setLength(stringBuilder.length() - 1);
+                    return ResponseResult.success("本地存在指定的流,有" + num + "协议", stringBuilder);
+                } else {
+                    return ResponseResult.success("本地不存在指定的流");
+                }
+            } else {
+                return ResponseResult.success(return_json);
+            }
+        } catch (Exception e) {
+            return ResponseResult.failed("查询指定流异常:" + e.getMessage());
+        }
+    }
+
+
+//    /**
+//     * 使用FFmpeg推拉流
+//     * 没有使用
+//     *
+//     * @param videoRequest
+//     * @return
+//     */
+//    @ParamCheck
+//    @PostMapping("addFFmpegSource")
+//    public CommonResult requestAddFFmpegSource(@RequestBody VideoRequest videoRequest) {
+//        List videoDTOList = videoRequest.getVideoList();
+//        List<VideoVO> videoVOList = new ArrayList<>();
+//
+//        for (int i = 0; i < videoDTOList.size(); i++) {
+//            VideoVO videoVO = new VideoVO();
+//            VideoDTO videoDTO = (VideoDTO) videoDTOList.get(i);
+//            String uri = "http://172.16.20.75:8081/index/api/addFFmpegSource" +
+//                    "?secret=035c73f7-bb6b-4889-a715-d9eb2d1925ca" +
+//                    "&src_url=rtsp://adnin:123456@" + videoDTO.getIp() + "/media/video" + videoDTO.getNowLine() +
+//                    "&dst_url=rtmp://172.16.20.75/live/stream" + i +
+//                    "&timeout_ms=10000" +
+//                    "&ffmpeg_cmd_key=ffmpeg.cmd";
+//
+//            RestTemplate restTemplate = new RestTemplate();
+//            ResponseEntity<String> forEntity = restTemplate.getForEntity(uri, String.class);
+//            ObjectMapper mapper = new ObjectMapper();
+//            try {
+//                Map<String, Object> jsonMap = mapper.readValue(forEntity.getBody(), new TypeReference<Map<String, Object>>() {
+//                });
+//                String data = jsonMap.get("data").toString();
+//                String substring = data.substring(5);
+//                String key = substring.substring(0, substring.length() - 1);
+//                videoVO.setKey(key);
+//            } catch (Exception e) {
+//                e.printStackTrace();
+//            }
+//            String flv = "http://172.16.20.75:8081/live/stream" + i + ".live.flv";
+//            videoVO.setUrlFlv(flv);
+//            videoVOList.add(videoVO);
+//        }
+//
+//        return CommonResult.ok().setResult(videoVOList);
+//    }
+
+
+//    /**
+//     * 关闭FFmpeg推拉流
+//     *
+//     * @param KeyRequest
+//     * @return
+//     */
+//    @ParamCheck
+//    @PostMapping("delFFmpegSource")
+//    public CommonResult requestDelFFmpegSource(@RequestBody KeyRequest KeyRequest) {
+//        String flag = "";
+//        List<KeyDTO> keyList = KeyRequest.getKeyList();
+//        for (int i = 0; i < keyList.size(); i++) {
+//            KeyDTO keyDTO = keyList.get(i);
+//            String cameraKey = this.queryCameraByIp(keyDTO.getIp()).getCameraKey();
+//            String uri = "http://172.16.20.75:8081/index/api/delFFmpegSource" +
+//                    "?secret=035c73f7-bb6b-4889-a715-d9eb2d1925ca" +
+//                    "&key=" + cameraKey;
+//
+//            RestTemplate restTemplate = new RestTemplate();
+//            ResponseEntity<String> forEntity = restTemplate.getForEntity(uri, String.class);
+//            ObjectMapper mapper = new ObjectMapper();
+//            try {
+//                Map<String, Object> jsonMap = mapper.readValue(forEntity.getBody(), new TypeReference<Map<String, Object>>() {
+//                });
+//                String data = jsonMap.get("data").toString();
+//                String substring = data.substring(6);
+//                flag = substring.substring(0, substring.length() - 1);
+//
+//            } catch (Exception e) {
+//                e.printStackTrace();
+//            }
+//        }
+//
+//        return CommonResult.ok().setResult(flag);
+//    }
+}

+ 91 - 0
src/main/java/com/chuanghai/video/core/ResponseResult.java

@@ -0,0 +1,91 @@
+package com.chuanghai.video.core;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 请求响应体
+ *
+ * @author zrx
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class ResponseResult implements Serializable {
+
+    private static final long serialVersionUID = 8041766238120354183L;
+
+    private int code;
+    private String status;
+    private String msg;
+    private Object data;
+
+    public static ResponseResult success(Object data) {
+        return ResponseResult.builder()
+                .code(ResponseStatus.SUCCESS.bCode)
+                .msg(ResponseStatus.SUCCESS.valueZh)
+                .status(ResponseStatus.SUCCESS.valueEn)
+                .data(data)
+                .build();
+    }
+
+    public static ResponseResult success(String msg, Object data) {
+        return ResponseResult.builder()
+                .code(ResponseStatus.SUCCESS.bCode)
+                .msg(ResponseStatus.SUCCESS.valueZh)
+                .status(ResponseStatus.SUCCESS.valueEn)
+                .msg(msg)
+                .data(data)
+                .build();
+    }
+    public static ResponseResult success(String msg) {
+        return ResponseResult.builder()
+                .code(ResponseStatus.SUCCESS.bCode)
+                .msg(msg)
+                .data(null)
+                .build();
+    }
+
+    public static ResponseResult failed(String msg) {
+        return failed(ResponseStatus.FAILED.bCode, msg);
+    }
+
+    public static ResponseResult failed(int code, String msg) {
+        return ResponseResult.builder()
+                .status(ResponseStatus.FAILED.valueEn)
+                .msg(msg)
+                .code(code)
+                .build();
+    }
+
+    // NOT_AUTHORIZED_EXCEPTION
+    public static ResponseResult noTokenAccess() {
+        return ResponseResult.builder()
+                .status(ResponseStatus.NOT_TOKEN_AUTHORIZED_EXCEPTION.valueEn)
+                .msg(ResponseStatus.NOT_TOKEN_AUTHORIZED_EXCEPTION.valueZh)
+                .code(ResponseStatus.NOT_TOKEN_AUTHORIZED_EXCEPTION.bCode)
+                .build();
+    }
+
+    // token过期
+    public static ResponseResult expiredTokenAccess() {
+        return ResponseResult.builder()
+                .status(ResponseStatus.EXPIRED_TOKEN_EXCEPTION.valueEn)
+                .msg(ResponseStatus.EXPIRED_TOKEN_EXCEPTION.valueZh)
+                .code(ResponseStatus.EXPIRED_TOKEN_EXCEPTION.bCode)
+                .build();
+    }
+    // token非法
+    public static ResponseResult invalidTokenAccess() {
+        return ResponseResult.builder()
+                .status(ResponseStatus.INVALID_TOKEN_EXCEPTION.valueEn)
+                .msg(ResponseStatus.INVALID_TOKEN_EXCEPTION.valueZh)
+                .code(ResponseStatus.INVALID_TOKEN_EXCEPTION.bCode)
+                .build();
+    }
+}

+ 159 - 0
src/main/java/com/chuanghai/video/core/ResponseStatus.java

@@ -0,0 +1,159 @@
+package com.chuanghai.video.core;
+
+/**
+ * 响应状态枚举
+ *
+ * @author zrx
+ */
+public enum ResponseStatus {
+
+	/**
+	 * 成功
+	 */
+	SUCCESS(200, 200, "yes", "成功", "返回成功"),
+
+	/**
+	 * 失败
+	 */
+	FAILED(-200, 417, "no", "失败", "异常失败"),
+
+	/**
+	 * 业务异常
+	 */
+	BUSINESS_EXCEPTION(2000, 200, "no", "网络连接不稳~请稍后再试", "业务异常"),
+
+	/**
+	 * 网络请求异常
+	 */
+	HTTP_CLIENT_EXCEPTION(4000, 400, "no", "网络连接不稳~请稍后再试", "网络请求异常: 第三方业务内部异常,请检查所访问的第三方业务是否正常"),
+
+	/**
+	 * 网络请求异常:第三方服务连接异常:请检查访问路径是否正常
+	 */
+	HTTP_CLIENT_CONNECTION_EXCEPTION(4004, 400, "no", "网络连接不稳~请稍后再试", "网络请求异常:第三方服务连接异常,请检查第三方访问路径是否正常"),
+
+	/**
+	 * 数据库异常
+	 */
+	DATA_ACCESS_EXCEPTION(6000, 500, "no", "服务器开小差~请稍后再试", "sql异常"),
+
+	/**
+	 * Valid参数校验异常
+	 */
+	VALID_EXCEPTION(5000, 400, "no", "服务器开小差~请稍后再试", "Valid参数校验异常"),
+
+	/**
+	 * 栈溢出
+	 */
+	STACK_OVERFLOW_ERROR(5001, 500, "no", "服务器开小差~请稍后再试", "栈溢出"),
+
+	/**
+	 * 其他错误
+	 */
+	OTHER_EXCEPTION(5002, 500, "no", "服务器开小差~请稍后再试", "其他错误"),
+
+	/**
+	 * 类型转换不支持异常
+	 */
+	CONVERSION_NOT_SUPPORTED_EXCEPTION(5003, 500, "no", "服务器开小差~请稍后再试", "类型转换不支持异常"),
+
+	/**
+	 * io异常
+	 */
+	IOException(5004, 500, "no", "服务器开小差~请稍后再试", "io异常"),
+
+	/**
+	 * 空指针异常
+	 */
+	NULL_POINTER_EXCEPTION(5005, 500, "no", "服务器开小差~请稍后再试", "空指针异常,请检查参数是否为空"),
+
+	/**
+	 * 未知方法异常
+	 */
+	NO_SUCH_METHOD_EXCEPTION(5006, 500, "no", "服务器开小差~请稍后再试", "未知方法异常"),
+
+	/**
+	 * 数组越界异常
+	 */
+	INDEX_OUT_OF_BOUNDS_EXCEPTION(5007, 500, "no", "服务器开小差~请稍后再试", "数组越界异常,请检查数组大小"),
+
+	/**
+	 * 无法找到该资源
+	 */
+	NOT_FOUND_EXCEPTION(5008, 500, "no", "无法找到该资源", "无法找到该资源"),
+
+	/**
+	 * 无授权访问,请先登录
+	 */
+	NOT_TOKEN_AUTHORIZED_EXCEPTION(401, 401, "no", "无授权访问,请先登录", "无授权访问,请先登录"),
+
+	/**
+	 * token过期,请从新登录
+	 */
+	EXPIRED_TOKEN_EXCEPTION(401, 401, "no", "token过期,请从新登录", "token过期,请从新登录"),
+
+	/**
+	 * token无效,请从新登录
+	 */
+	INVALID_TOKEN_EXCEPTION(401, 401, "no", "token无效,请从新登录", "token无效,请从新登录"),
+
+	/**
+	 * 类型不匹配异常
+	 */
+	TYPE_MISMATCH_EXCEPTION(400, 400, "no", "服务器开小差~请稍后再试", "类型不匹配异常"),
+
+	/**
+	 * 类型不匹配异常
+	 */
+	MISSING_SERVLET_REQUEST_PARAMETER_EXCEPTION(400, 400, "no", "服务器开小差~请稍后再试", "类型不匹配异常"),
+
+	/**
+	 * http媒体类型不支持异常
+	 */
+	NOT_ACCEPTABLE(406, 406, "no", "服务器开小差~请稍后再试", "http媒体类型不支持异常"),
+
+	/**
+	 * 方法不允许
+	 */
+	METHOD_NOT_ALLOWED(405, 405, "no", "方法不允许", "方法不允许"),
+
+	/**
+	 * 运行时异常
+	 */
+	RUNTIME_EXCEPTION(500, 500, "no", "服务器开小差~请稍后再试", "运行时异常"),
+
+	/**
+	 * 类型转换异常
+	 */
+	CLASS_CAST_EXCEPTION(5009, 500, "no", "服务器开小差~请稍后再试", "类型转换异常");
+
+	/**
+	 * 业务code
+	 */
+	public Integer bCode;
+	/**
+	 * http code
+	 */
+	public Integer hCode;
+	/**
+	 * 英文状态值
+	 */
+	public String valueEn;
+	/**
+	 * 返回给前端的中文说明
+	 */
+	public String valueZh;
+	/**
+	 * 存储日志的中文说明
+	 */
+	public String valueLog;
+
+	ResponseStatus(Integer bCode, Integer hCode, String valueEn, String valueZh, String valueLog) {
+		this.bCode = bCode;
+		this.hCode = hCode;
+		this.valueEn = valueEn;
+		this.valueZh = valueZh;
+		this.valueLog = valueLog;
+	}
+
+}

+ 79 - 0
src/main/java/com/chuanghai/video/core/interceptor/JwtInterceptor.java

@@ -0,0 +1,79 @@
+package com.chuanghai.video.core.interceptor;
+
+import com.alibaba.fastjson2.JSON;
+import com.chuanghai.video.core.ResponseResult;
+import com.chuanghai.video.entity.Admin;
+import com.chuanghai.video.util.JwtUtil;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+
+@Component
+public class JwtInterceptor implements HandlerInterceptor {
+
+    @Autowired
+    private JwtUtil jwtUtil;
+
+    @Value("${myapp.mypre}")
+    private String prefix;
+
+    @Override
+    public boolean preHandle(HttpServletRequest request,
+                             @NotNull HttpServletResponse response,
+                             @NotNull Object handler) throws Exception {
+        // 获取token
+        String authHeader = request.getHeader("Admin_token");
+        // 可能有大小写之分
+        if (authHeader != null)
+            authHeader = request.getHeader("admin_token");
+        // 不为null 并且有指定的前缀
+        if (authHeader != null && authHeader.startsWith(prefix)) {
+            // 去除前缀
+            String token = authHeader.substring(prefix.length());
+            // 从token获取用户名
+            String usernameFromToken = jwtUtil.getUsernameFromToken(token);
+            // 如果为空,响应客户端token无效,并返回false
+            if ("".equals(usernameFromToken)) {
+                response.setCharacterEncoding("UTF-8");
+                response.setContentType("application/json");
+
+                String json = JSON.toJSONString(ResponseResult.invalidTokenAccess());
+
+                response.getWriter().write(json);
+
+                return false;
+            }
+            Admin admin = new Admin();
+            // 否则,设置用户名
+            admin.setUsername(usernameFromToken);
+            // 验证token
+            if (jwtUtil.validateToken(token, admin)) {
+                return true;
+            } else {
+                // response.setStatus(HttpStatus.UNAUTHORIZED.value());
+                response.setCharacterEncoding("UTF-8");
+                response.setContentType("application/json");
+
+                String json = JSON.toJSONString(ResponseResult.expiredTokenAccess());
+
+                response.getWriter().write(json);
+                return false;
+            }
+        } else {
+            // response.setStatus(HttpStatus.UNAUTHORIZED.value());
+            response.setCharacterEncoding("UTF-8");
+            response.setContentType("application/json");
+
+            String json = JSON.toJSONString(ResponseResult.noTokenAccess());
+
+            response.getWriter().write(json);
+            return false;
+        }
+    }
+}

+ 35 - 0
src/main/java/com/chuanghai/video/entity/Admin.java

@@ -0,0 +1,35 @@
+package com.chuanghai.video.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.sql.Timestamp;
+
+@TableName("video_admin")
+@Data
+public class Admin {
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    private String id;
+    private String username;
+    private String phone;
+    private String adminType;
+    private String password;
+    private Timestamp createTime;
+    private Timestamp updateTime;
+    private Integer statu;
+    private Integer sex;
+    private String name;
+
+    @TableField(exist=false)
+    private Integer pageNum;
+    @TableField(exist=false)
+    private Integer pageSize;
+    @TableField(exist=false)
+    private Timestamp startTime;
+    @TableField(exist=false)
+    private Timestamp endTime;
+
+}

+ 59 - 0
src/main/java/com/chuanghai/video/entity/Camera.java

@@ -0,0 +1,59 @@
+package com.chuanghai.video.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.math.BigInteger;
+import java.sql.Timestamp;
+
+@TableName("video_camera")
+@Data
+public class Camera {
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    private BigInteger id;
+    private String unitType;
+    private String vendor;
+    private String agreement;
+    private String installationSite;
+    private String spot;
+    private String channel;
+    private String d;
+    private String ip;
+    private String ipPassword;
+    private String cameraCoding;
+    private String online;
+    private String statu;
+    private String remark;
+    private String creater;
+    private Timestamp createTime;
+    private String lastUpdater;
+    private Timestamp lastUpdateTime;
+
+    @TableField(exist = false)
+    private Integer pageNum;
+    @TableField(exist = false)
+    private Integer pageSize;
+    @TableField(exist = false)
+    private Timestamp startCreateTime;
+    @TableField(exist = false)
+    private Timestamp endCreateTime;
+    @TableField(exist = false)
+    private Timestamp startLastUpdateTime;
+    @TableField(exist = false)
+    private Timestamp endLastUpdateTime;
+    @TableField(exist = false)
+    private String orderField;
+    @TableField(exist = false)
+    private String order;
+    @TableField(exist = false)
+    private String regularExpression;
+    @TableField(exist = false)
+    private String nowLine;
+    @TableField(exist = false)
+    private String videoLinks;
+}
+
+

+ 13 - 0
src/main/java/com/chuanghai/video/entity/CameraRelationship.java

@@ -0,0 +1,13 @@
+package com.chuanghai.video.entity;
+
+import lombok.Data;
+
+@Data
+public class CameraRelationship {
+    private String installationSite;
+    private String spotName;
+    private String channel;
+    private String d;
+}
+
+

+ 34 - 0
src/main/java/com/chuanghai/video/entity/Config.java

@@ -0,0 +1,34 @@
+package com.chuanghai.video.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+import java.math.BigInteger;
+import java.sql.Timestamp;
+
+@Data
+public class Config {
+    @TableId(value = "id")
+    private BigInteger id;
+    private String cfgClass;
+    private String cfgName;
+    private String cfgValue;
+    private String cfgDescription;
+    private String allowUpdate;
+    private String createdTime;
+    private String updatedTime;
+
+    @TableField(exist = false)
+    private Integer pageNum;
+    @TableField(exist = false)
+    private Integer pageSize;
+    @TableField(exist = false)
+    private Timestamp startCreateTime;
+    @TableField(exist = false)
+    private Timestamp endCreateTime;
+    @TableField(exist = false)
+    private Timestamp startLastUpdateTime;
+    @TableField(exist = false)
+    private Timestamp endLastUpdateTime;
+}

+ 23 - 0
src/main/java/com/chuanghai/video/entity/Player.java

@@ -0,0 +1,23 @@
+package com.chuanghai.video.entity;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+import java.math.BigInteger;
+import java.sql.Timestamp;
+
+@Data
+public class Player {
+    @TableId(value = "id")
+    private BigInteger id;
+    private String ip;
+    private String playerkey;
+    private String channel;
+    private String d;
+    private String nowLine;
+    private int playerCount;
+    private String vendor;
+    private String videoLinks;
+    private Timestamp createTime;
+    private Timestamp updateTime;
+}

+ 27 - 0
src/main/java/com/chuanghai/video/entity/Spot.java

@@ -0,0 +1,27 @@
+package com.chuanghai.video.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+import java.sql.Timestamp;
+
+@Data
+public class Spot {
+    @TableId(value = "id")
+    private Integer id;
+    private String spotName;
+    private String nvrIp;
+    private String ipPassword;
+    private String createdTime;
+    private String updatedTime;
+
+    @TableField(exist=false)
+    private Integer pageNum;
+    @TableField(exist=false)
+    private Integer pageSize;
+    @TableField(exist=false)
+    private Timestamp startTime;
+    @TableField(exist=false)
+    private Timestamp endTime;
+}

+ 81 - 0
src/main/java/com/chuanghai/video/mapper/AdminMapper.java

@@ -0,0 +1,81 @@
+package com.chuanghai.video.mapper;
+
+import com.chuanghai.video.entity.Admin;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+
+@Mapper
+public interface AdminMapper {
+
+    @Select("SELECT username, password FROM video_admin WHERE username=#{username} limit 1")
+    List<Admin> login(Admin admin);
+
+    @Select("SELECT username FROM video_admin WHERE username=#{username} OR phone=#{phone} limit 1")
+    List<Admin> queryByUsernameOrPhone(Admin admin);
+
+    @Select("SELECT username FROM video_admin WHERE username=#{username} AND password=#{password} AND adminType=#{adminType} AND " +
+            "sex=#{sex} AND phone=#{phone} AND name=#{name} limit 1")
+    List<Admin> queryByUsernameOrPhoneOrOthers(Admin admin);
+
+    @Select({
+            "<script>",
+            "SELECT id, username, phone, adminType, createTime, updateTime, statu, sex, name FROM video_admin",
+            "<where>",
+            "<if test='name != null'>AND name like CONCAT('%', #{name}, '%')</if>",
+            "<if test='phone != null'>AND phone like CONCAT('%', #{phone}, '%')</if>",
+            "<if test='adminType != null'>AND adminType = #{adminType}</if>",
+            "<if test='startTime != null'>AND createTime &gt;= #{startTime}</if>",
+            "<if test='endTime != null'>AND createTime &lt; #{endTime}</if>",
+            "</where>",
+            "</script>"
+    })
+    List<Admin> list(Admin admin);
+
+    @Insert({
+            "<script>",
+            "INSERT INTO video_admin",
+            "<trim prefix='(' suffix=')' suffixOverrides=','>",
+            "<if test='username != null'>username,</if>",
+            "<if test='password != null'>password,</if>",
+            "<if test='phone != null'>phone,</if>",
+            "<if test='adminType != null'>adminType,</if>",
+            "<if test='statu != null'>statu,</if>",
+            "<if test='sex != null'>sex,</if>",
+            "<if test='name != null'>name,</if>",
+            "</trim>",
+            "VALUES",
+            "<trim prefix='(' suffix=')' suffixOverrides=','>",
+            "<if test='username != null'>#{username},</if>",
+            "<if test='password != null'>#{password},</if>",
+            "<if test='phone != null'>#{phone},</if>",
+            "<if test='adminType != null'>#{adminType},</if>",
+            "<if test='statu != null'>#{statu},</if>",
+            "<if test='sex != null'>#{sex},</if>",
+            "<if test='name != null'>#{name},</if>",
+            "</trim>",
+            "</script>"
+    })
+    int add(Admin admin);
+
+    @Update({
+            "<script>",
+            "UPDATE video_admin",
+            "SET",
+            "<trim suffixOverrides=','>",
+            "<if test='username != null'>username = #{username},</if>",
+            "<if test='password != null'>password = #{password},</if>",
+            "<if test='phone != null'>phone = #{phone},</if>",
+            "<if test='adminType != null'>adminType = #{adminType},</if>",
+            "<if test='statu != null'>statu = #{statu},</if>",
+            "<if test='sex != null'>sex = #{sex},</if>",
+            "<if test='name != null'>name = #{name},</if>",
+            "</trim>",
+            "WHERE id = #{id}",
+            "</script>"
+    })
+    int update(Admin admin);
+
+    @Delete("DELETE FROM video_admin WHERE id = #{id}")
+    int delete(String id);
+}

+ 245 - 0
src/main/java/com/chuanghai/video/mapper/CameraMapper.java

@@ -0,0 +1,245 @@
+package com.chuanghai.video.mapper;
+
+import com.chuanghai.video.entity.Camera;
+import com.chuanghai.video.entity.CameraRelationship;
+import com.chuanghai.video.entity.Spot;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+
+@Mapper
+public interface CameraMapper {
+
+    @Select({
+            "<script>",
+            "SELECT vc.id, vc.unitType, vc.vendor, vc.agreement, vc.installationSite, vs.spotName, vc.spot, vc.channel, vc.d, vc.ip, vc.ipPassword, " +
+                    "vc.cameraCoding, vc.online, vc.statu, vc.remark, vc.creater, vc.createTime, vc.lastUpdater, " +
+                    "vc.lastUpdateTime, p.videoLinks ",
+            "FROM video_camera vc",
+            "LEFT JOIN video_spot vs ON vc.spot = vs.id", // 添加与video_spot表的连接
+            "LEFT JOIN video_player p ON vc.ip = p.ip",
+            "<where>",
+            "<if test='unitType != null'>AND vc.unitType like CONCAT('%', #{unitType}, '%')</if>",
+            "<if test='vendor != null'>AND vc.vendor like CONCAT('%', #{vendor}, '%')</if>",
+            "<if test='agreement != null'>AND vc.agreement like CONCAT('%', #{agreement}, '%')</if>",
+            "<if test='installationSite != null'>AND vc.installationSite like CONCAT('%', #{installationSite}, '%')</if>",
+            "<if test='spot != null'>AND vs.spotName like CONCAT('%', #{spot}, '%')</if>",
+            "<if test='channel != null'>AND vc.channel like CONCAT('%', #{channel}, '%')</if>",
+            "<if test='d != null'>AND vc.d = #{d}</if>",
+            "<if test='ip != null'>AND vc.ip like CONCAT('%', #{ip}, '%')</if>",
+            "<if test='ipPassword != null'>AND vc.ipPassword like CONCAT('%', #{ipPassword}, '%')</if>",
+            "<if test='cameraCoding != null'>AND vc.cameraCoding like CONCAT('%', #{cameraCoding}, '%')</if>",
+            "<if test='online != null'>AND vc.online = #{online}</if>",
+            "<if test='statu != null'>AND vc.statu = #{statu}</if>",
+            "<if test='remark != null'>AND vc.remark like CONCAT('%', #{remark}, '%')</if>",
+            "<if test='creater != null'>AND vc.creater like CONCAT('%', #{creater}, '%')</if>",
+            "<if test='startCreateTime != null'>AND vc.createTime &gt;= #{startCreateTime}</if>",
+            "<if test='endCreateTime != null'>AND vc.createTime &lt;= #{endCreateTime}</if>",
+            "<if test='lastUpdater != null'>AND vc.lastUpdater like CONCAT('%', #{lastUpdater}, '%')</if>",
+            "<if test='startLastUpdateTime != null'>AND vc.lastUpdateTime &gt;= #{startLastUpdateTime}</if>",
+            "<if test='endLastUpdateTime != null'>AND vc.lastUpdateTime &lt;= #{endLastUpdateTime}</if>",
+            "</where>",
+            "<if test='orderField != null and order != null'>",
+            "ORDER BY ${orderField} ${order}",
+            "</if>",
+            "</script>"
+    })
+    List<Camera> list(Camera camera);
+
+    @Select({
+            "<script>",
+            " SELECT vs.spotName, vc.installationSite, vc.d, vc.channel ",
+            " FROM video_spot vs ",
+            " LEFT JOIN video_camera vc ON vs.id = vc.spot",
+            " ORDER BY vs.spotName",
+            "</script>"
+    })
+    List<CameraRelationship> list_camera_relationship();
+
+    @Select({
+            "<script>",
+            "SELECT id ",
+            "FROM video_camera ",
+            "<where>",
+            "<if test='installationSite != null'>AND installationSite = #{installationSite}</if>",
+            "<if test='ip != null'>OR ip = #{ip}</if>",
+            "<if test='channel != null'>OR channel = #{channel}</if>",
+            "<if test='d != null'>OR d = #{d}</if>",
+            "</where>",
+            "</script>"
+    })
+    List<Camera> queryByIpOrinstallationSite(Camera camera);
+
+    @Select({
+            "<script>",
+            "SELECT id, unitType, vendor, agreement, installationSite, spot, channel, d, ip, ipPassword, cameraCoding, online, statu, remark, creater, createTime, lastUpdater, lastUpdateTime ",
+            "FROM video_camera ",
+            "<where>",
+            "<if test='unitType != null'>AND unitType like CONCAT('%', #{unitType}, '%')</if>",
+            "<if test='vendor != null'>AND vendor like CONCAT('%', #{vendor}, '%')</if>",
+            "<if test='agreement != null'>AND agreement like CONCAT('%', #{agreement}, '%')</if>",
+            "<if test='installationSite != null'>AND installationSite like CONCAT('%', #{installationSite}, '%')</if>",
+            "<if test='regularExpression != null'>AND installationSite REGEXP #{regularExpression}</if>",
+            "<if test='spot != null'>AND vc.spot like CONCAT('%', #{spot}, '%')</if>",
+            "<if test='channel != null'>AND vc.channel like CONCAT('%', #{channel}, '%')</if>",
+            "<if test='d != null'>AND vc.d = #{d}</if>",
+            "<if test='ip != null'>AND ip like CONCAT('%', #{ip}, '%')</if>",
+            "<if test='ipPassword != null'>AND ipPassword like CONCAT('%', #{ipPassword}, '%')</if>",
+            "<if test='cameraCoding != null'>AND cameraCoding like CONCAT('%', #{cameraCoding}, '%')</if>",
+            "<if test='online != null'>AND online = #{online}</if>",
+            "<if test='statu != null'>AND statu = #{statu}</if>",
+            "<if test='remark != null'>AND remark like CONCAT('%', #{remark}, '%')</if>",
+            "<if test='creater != null'>AND creater like CONCAT('%', #{creater}, '%')</if>",
+            "<if test='createTime != null'>AND createTime &gt;= #{startCreateTime}</if>",
+            "<if test='createTime != null'>AND createTime &lt; #{endCreateTime}</if>",
+            "<if test='lastUpdater != null'>AND lastUpdater like CONCAT('%', #{lastUpdater}, '%')</if>",
+            "<if test='lastUpdateTime != null'>AND lastUpdateTime &gt;= #{startLastUpdateTime}</if>",
+            "<if test='lastUpdateTime != null'>AND lastUpdateTime &lt; #{endLastUpdateTime}</if>",
+            "</where>",
+            "<if test='orderField != null and order != null'>",
+            "ORDER BY ${orderField} ${order}",
+            "</if>",
+            "</script>"
+    })
+    List<Camera> listByRegexp(Camera camera);
+
+    @Insert({
+            "<script>",
+            "INSERT INTO video_camera",
+            "<trim prefix='(' suffix=')' suffixOverrides=','>",
+            "<if test='online != null'>online,</if>",
+            "<if test='unitType != null'>unitType,</if>",
+            "<if test='vendor != null'>vendor,</if>",
+            "<if test='agreement != null'>agreement,</if>",
+            "<if test='installationSite != null'>installationSite,</if>",
+            "<if test='spot != null'>spot,</if>",
+            "<if test='channel != null'>channel,</if>",
+            "<if test='d != null'>d,</if>",
+            "<if test='ip != null'>ip,</if>",
+            "<if test='ipPassword != null'>ipPassword,</if>",
+            "<if test='cameraCoding != null'>cameraCoding,</if>",
+            "<if test='statu != null'>statu,</if>",
+            "<if test='remark != null'>remark,</if>",
+            "<if test='creater != null'>creater,</if>",
+            "<if test='lastUpdater != null'>lastUpdater,</if>",
+            "</trim>",
+            "VALUES",
+            "<trim prefix='(' suffix=')' suffixOverrides=','>",
+            "<if test='online != null'>#{online},</if>",
+            "<if test='unitType != null'>#{unitType},</if>",
+            "<if test='vendor != null'>#{vendor},</if>",
+            "<if test='agreement != null'>#{agreement},</if>",
+            "<if test='installationSite != null'>#{installationSite},</if>",
+            "<if test='spot != null'>#{spot},</if>",
+            "<if test='channel != null'>#{channel},</if>",
+            "<if test='d != null'>#{d},</if>",
+            "<if test='ip != null'>#{ip},</if>",
+            "<if test='ipPassword != null'>#{ipPassword},</if>",
+            "<if test='cameraCoding != null'>#{cameraCoding},</if>",
+            "<if test='statu != null'>#{statu},</if>",
+            "<if test='remark != null'>#{remark},</if>",
+            "<if test='creater != null'>#{creater},</if>",
+            "<if test='lastUpdater != null'>#{lastUpdater},</if>",
+            "</trim>",
+            "</script>"
+    })
+    int add(Camera camera);
+
+    @Update({
+            "<script>",
+            "UPDATE video_camera",
+            "SET",
+            "<trim suffixOverrides=','>",
+            "<if test='online != null'>online = #{online},</if>",
+            "<if test='unitType != null'>unitType = #{unitType},</if>",
+            "<if test='vendor != null'>vendor = #{vendor},</if>",
+            "<if test='agreement != null'>agreement = #{agreement},</if>",
+            "<if test='installationSite != null'>installationSite = #{installationSite},</if>",
+            "<if test='spot != null'>spot = #{spot},</if>",
+            "<if test='channel != null'>channel = #{channel},</if>",
+            "<if test='d != null'>d = #{d},</if>",
+            "<if test='ip != null'>ip = #{ip},</if>",
+            "<if test='ipPassword != null'>ipPassword = #{ipPassword},</if>",
+            "<if test='cameraCoding != null'>cameraCoding = #{cameraCoding},</if>",
+            "<if test='statu != null'>statu = #{statu},</if>",
+            "<if test='remark != null'>remark = #{remark},</if>",
+            "<if test='creater != null'>creater = #{creater},</if>",
+            "<if test='lastUpdater != null'>lastUpdater = #{lastUpdater},</if>",
+            "</trim>",
+            "WHERE id = #{id}",
+            "</script>"
+    })
+    int update(Camera camera);
+
+    @Delete("DELETE FROM video_camera WHERE id = #{id}")
+    int delete(String id);
+
+    @Insert({
+            "<script>",
+            "INSERT INTO video_camera",
+            "<trim prefix='(' suffix=')' suffixOverrides=','>",
+            "<if test='online != null'>online,</if>",
+            "<if test='unitType != null'>unitType,</if>",
+            "<if test='vendor != null'>vendor,</if>",
+            "<if test='agreement != null'>agreement,</if>",
+            "<if test='installationSite != null'>installationSite,</if>",
+            "<if test='ip != null'>ip,</if>",
+            "<if test='ipPassword != null'>ipPassword,</if>",
+            "<if test='cameraCoding != null'>cameraCoding,</if>",
+            "<if test='statu != null'>statu,</if>",
+            "<if test='remark != null'>remark,</if>",
+            "<if test='creater != null'>creater,</if>",
+            "<if test='lastUpdater != null'>lastUpdater,</if>",
+            "</trim>",
+            "VALUES",
+            "<trim prefix='(' suffix=')' suffixOverrides=','>",
+            "<if test='online != null'>#{online},</if>",
+            "<if test='unitType != null'>#{unitType},</if>",
+            "<if test='vendor != null'>#{vendor},</if>",
+            "<if test='agreement != null'>#{agreement},</if>",
+            "<if test='installationSite != null'>#{installationSite},</if>",
+            "<if test='ip != null'>#{ip},</if>",
+            "<if test='ipPassword != null'>#{ipPassword},</if>",
+            "<if test='cameraCoding != null'>#{cameraCoding},</if>",
+            "<if test='statu != null'>#{statu},</if>",
+            "<if test='remark != null'>#{remark},</if>",
+            "<if test='creater != null'>#{creater},</if>",
+            "<if test='lastUpdater != null'>#{lastUpdater},</if>",
+            "</trim>",
+            "</script>"
+    })
+    int importExcelToTable(Camera camera);
+
+    @Select({
+            "<script>",
+            "SELECT id, spotName, nvrIp, ipPassword ",
+            "FROM video_spot ",
+            "<where>",
+            "<if test='id != null'>AND id = #{id}</if>",
+            "</where>",
+            "</script>"
+    })
+    List<Spot> getSpotInfo(int spot);
+
+    @Select({
+            "<script>",
+            "SELECT id, spotName, nvrIp, ipPassword ",
+            "FROM video_spot ",
+            "<where>",
+            "<if test='spotName != null'>AND spotName = #{spotName}</if>",
+            "</where>",
+            "</script>"
+    })
+    List<Spot> querySpotIdBySpotName(String spotName);
+
+    @Select({
+            "<script>",
+            "SELECT channel ",
+            "FROM video_camera ",
+            "<where>",
+            "<if test='d != null'>OR d = #{d}</if>",
+            "</where>",
+            "</script>"
+    })
+    List<Camera> queryChannel(Camera camera);
+}

+ 46 - 0
src/main/java/com/chuanghai/video/mapper/ConfigMapper.java

@@ -0,0 +1,46 @@
+package com.chuanghai.video.mapper;
+
+import com.chuanghai.video.entity.Config;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+
+import java.util.List;
+
+@Mapper
+public interface ConfigMapper {
+
+    @Update({
+            "<script>",
+            "UPDATE video_config",
+            "SET",
+            "<trim suffixOverrides=','>",
+            "<if test='cfgValue != null'>cfgValue = #{cfgValue},</if>",
+            "</trim>",
+            "<where>",
+            "<if test='cfgClass != null'>AND cfgClass = #{cfgClass}</if>",
+            "<if test='cfgName != null'>AND cfgName = #{cfgName}</if>",
+            "</where>",
+            "</script>"
+    })
+    int updateConfig(Config config);
+
+    @Select({
+            "<script>",
+            "   SELECT * FROM video_config",
+            "   <where>",
+            "       <if test='cfgClass != null'>AND cfgClass like CONCAT('%', #{cfgClass}, '%')</if>",
+            "       <if test='cfgName != null'>AND cfgName like CONCAT('%', #{cfgName}, '%')</if>",
+            "   <if test='cfgValue != null'>AND cfgValue = #{cfgValue}</if>",
+            "   <if test='cfgDescription != null'>AND cfgDescription like CONCAT('%', #{cfgDescription}, '%')</if>",
+            "   <if test='allowUpdate != null'>AND allowUpdate = #{allowUpdate}</if>",
+            "   <if test='startCreateTime != null'>AND createdTime &gt;= #{startCreateTime}</if>",
+            "   <if test='endCreateTime != null'>AND createdTime &lt;= #{endCreateTime}</if>",
+            "   <if test='startLastUpdateTime != null'>AND updatedTime &gt;= #{startLastUpdateTime}</if>",
+            "   <if test='endLastUpdateTime != null'>AND updatedTime &lt;= #{endLastUpdateTime}</if>",
+            "   </where>",
+            "       ORDER BY cfgClass, cfgName",
+            "</script>"
+    })
+    List<Config> listConfig(Config config);
+}

+ 65 - 0
src/main/java/com/chuanghai/video/mapper/SpotMapper.java

@@ -0,0 +1,65 @@
+package com.chuanghai.video.mapper;
+
+import com.chuanghai.video.entity.Spot;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+
+@Mapper
+public interface SpotMapper {
+
+    @Select("SELECT spotName FROM video_spot WHERE spotName=#{spotName} OR nvrIp=#{nvrIp}")
+    List<Spot> queryBySpotNameOrNvrIp(Spot spot);
+
+    @Select("SELECT spotName FROM video_spot WHERE spotName=#{spotName} AND nvrIp=#{nvrIp} AND ipPassword=#{ipPassword}")
+    List<Spot> queryBySpotnameOrNvrIpOrOthers(Spot spot);
+
+    @Select({
+            "<script>",
+            "SELECT * FROM video_spot vs",
+            "<where>",
+            "<if test='spotName != null'>AND spotName like CONCAT('%', #{spotName}, '%')</if>",
+            "<if test='nvrIp != null'>AND nvrIp like CONCAT('%', #{nvrIp}, '%')</if>",
+            "<if test='ipPassword != null'>AND ipPassword like CONCAT('%', #{ipPassword}, '%')</if>",
+            "<if test='startTime != null'>AND createTime &gt;= #{startTime}</if>",
+            "<if test='endTime != null'>AND createTime &lt; #{endTime}</if>",
+            "</where>",
+            "</script>"
+    })
+    List<Spot> list(Spot spot);
+
+    @Insert({
+            "<script>",
+            "INSERT INTO video_spot",
+            "<trim prefix='(' suffix=')' suffixOverrides=','>",
+            "<if test='spotName != null'>spotName,</if>",
+            "<if test='nvrIp != null'>nvrIp,</if>",
+            "<if test='ipPassword != null'>ipPassword,</if>",
+            "</trim>",
+            "VALUES",
+            "<trim prefix='(' suffix=')' suffixOverrides=','>",
+            "<if test='spotName != null'>#{spotName},</if>",
+            "<if test='nvrIp != null'>#{nvrIp},</if>",
+            "<if test='ipPassword != null'>#{ipPassword},</if>",
+            "</trim>",
+            "</script>"
+    })
+    int add(Spot spot);
+
+    @Update({
+            "<script>",
+            "UPDATE video_spot",
+            "SET",
+            "<trim suffixOverrides=','>",
+            "<if test='spotName != null'>spotName = #{spotName},</if>",
+            "<if test='nvrIp != null'>nvrIp = #{nvrIp},</if>",
+            "<if test='ipPassword != null'>ipPassword = #{ipPassword},</if>",
+            "</trim>",
+            "WHERE id = #{id}",
+            "</script>"
+    })
+    int update(Spot spot);
+
+    @Delete("DELETE FROM video_spot WHERE id = #{id}")
+    int delete(String id);
+}

+ 116 - 0
src/main/java/com/chuanghai/video/mapper/VideoMapper.java

@@ -0,0 +1,116 @@
+package com.chuanghai.video.mapper;
+
+import com.chuanghai.video.entity.Camera;
+import com.chuanghai.video.entity.Config;
+import com.chuanghai.video.entity.Player;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+
+@Mapper
+public interface VideoMapper {
+
+    @Select("SELECT * FROM video_config")
+    List<Config> getConfig();
+
+    @Select({
+            "<script>",
+            "SELECT * FROM video_player",
+            "<where>",
+            "<if test='d != null'>AND d = #{d}</if>",
+            "<if test='nowLine != null'>AND nowLine = #{nowLine}</if>",
+            "</where>",
+            "</script>"
+    })
+    List<Player> queryPlayer(Player player);
+
+    @Insert({
+            "<script>",
+            "INSERT INTO video_player",
+            "<trim prefix='(' suffix=')' suffixOverrides=','>",
+            "<if test='ip != null'>ip,</if>",
+            "<if test='playerkey != null'>playerkey,</if>",
+            "<if test='channel != null'>channel,</if>",
+            "<if test='d != null'>d,</if>",
+            "<if test='nowLine != null'>nowLine,</if>",
+            "<if test='playerCount != null'>playerCount,</if>",
+            "<if test='vendor != null'>vendor,</if>",
+            "<if test='videoLinks != null'>videoLinks,</if>",
+            "</trim>",
+            "VALUES",
+            "<trim prefix='(' suffix=')' suffixOverrides=','>",
+            "<if test='ip != null'>#{ip},</if>",
+            "<if test='playerkey != null'>#{playerkey},</if>",
+            "<if test='channel != null'>#{channel},</if>",
+            "<if test='d != null'>#{d},</if>",
+            "<if test='nowLine != null'>#{nowLine},</if>",
+            "<if test='playerCount != null'>#{playerCount},</if>",
+            "<if test='vendor != null'>#{vendor},</if>",
+            "<if test='videoLinks != null'>#{videoLinks},</if>",
+            "</trim>",
+            "</script>"
+    })
+    int add(Player player);
+
+    @Update({
+            "<script>",
+            "UPDATE video_player",
+            "SET",
+            "<trim suffixOverrides=','>",
+            "<if test='ip != null'>ip = #{ip},</if>",
+            "<if test='playerkey != null'>playerkey = #{playerkey},</if>",
+            "<if test='channel != null'>channel = #{channel},</if>",
+            "<if test='d != null'>d = #{d},</if>",
+            "<if test='nowLine != null'>nowLine = #{nowLine},</if>",
+            "<if test='playerCount != null'>playerCount = #{playerCount},</if>",
+            "<if test='vendor != null'>vendor = #{vendor},</if>",
+            "<if test='videoLinks != null'>videoLinks = #{videoLinks},</if>",
+            "</trim>",
+            "WHERE id = #{id}",
+            "</script>"
+    })
+    int updatePlayer(Player player);
+
+    @Delete("DELETE FROM video_player WHERE id = #{id}")
+    int delete(String id);
+
+    @Delete("DELETE FROM video_player WHERE playerkey like CONCAT('%', #{key})")
+    int deleteByKey(String key);
+
+//    @Insert({
+//            "<script>",
+//            "INSERT INTO video_camera",
+//            "<trim prefix='(' suffix=')' suffixOverrides=','>",
+//            "<if test='online != null'>online,</if>",
+//            "<if test='unitType != null'>unitType,</if>",
+//            "<if test='vendor != null'>vendor,</if>",
+//            "<if test='agreement != null'>agreement,</if>",
+//            "<if test='installationSite != null'>installationSite,</if>",
+//            "<if test='ip != null'>ip,</if>",
+//            "<if test='ipPassword != null'>ipPassword,</if>",
+//            "<if test='cameraCoding != null'>cameraCoding,</if>",
+//            "<if test='statu != null'>statu,</if>",
+//            "<if test='remark != null'>remark,</if>",
+//            "<if test='creater != null'>creater,</if>",
+//            "<if test='lastUpdater != null'>lastUpdater,</if>",
+//            "</trim>",
+//            "VALUES",
+//            "<trim prefix='(' suffix=')' suffixOverrides=','>",
+//            "<if test='online != null'>#{online},</if>",
+//            "<if test='unitType != null'>#{unitType},</if>",
+//            "<if test='vendor != null'>#{vendor},</if>",
+//            "<if test='agreement != null'>#{agreement},</if>",
+//            "<if test='installationSite != null'>#{installationSite},</if>",
+//            "<if test='ip != null'>#{ip},</if>",
+//            "<if test='ipPassword != null'>#{ipPassword},</if>",
+//            "<if test='cameraCoding != null'>#{cameraCoding},</if>",
+//            "<if test='statu != null'>#{statu},</if>",
+//            "<if test='remark != null'>#{remark},</if>",
+//            "<if test='creater != null'>#{creater},</if>",
+//            "<if test='lastUpdater != null'>#{lastUpdater},</if>",
+//            "</trim>",
+//            "</script>"
+//    })
+//    int importExcelToTable(Camera camera);
+
+}

+ 28 - 0
src/main/java/com/chuanghai/video/util/CommonUtil.java

@@ -0,0 +1,28 @@
+package com.chuanghai.video.util;
+
+import com.alibaba.fastjson2.JSONObject;
+
+import java.util.Iterator;
+
+public class CommonUtil {
+
+    /**
+     * 拼接URL参数
+     * @param jsonParams
+     * @return
+     */
+    public String urlParams(JSONObject jsonParams) {
+        Iterator<String> it = jsonParams.keySet().iterator();
+        StringBuilder paramStr = new StringBuilder();
+        while (it.hasNext()) {
+            String key = it.next();
+            String value = jsonParams.getString(key);
+            paramStr.append("&").append(key).append("=").append(value);
+        }
+
+        paramStr.replace(0, 1, "?");
+
+        return paramStr.toString();
+    }
+
+}

+ 87 - 0
src/main/java/com/chuanghai/video/util/DateTimeUtil.java

@@ -0,0 +1,87 @@
+package com.chuanghai.video.util;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.TextStyle;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+public class DateTimeUtil {
+
+    /**
+     * 获取年月日时分秒周
+     *
+     * @param startDate
+     * @return
+     */
+    public Map<String, Integer> getDateTime(String startDate) {
+        LocalDateTime now = LocalDateTime.now();
+        int year = now.getYear();
+        int month = now.getMonthValue();
+        int day = now.getDayOfMonth();
+        int hour = now.getHour();
+        int minute = now.getMinute();
+        int second = now.getSecond();
+        Map<String, Integer> map = new HashMap<>();
+        map.put("year", year);
+        map.put("month", month);
+        map.put("day", day);
+        map.put("hour", hour);
+        map.put("minute", minute);
+        map.put("second", second);
+        // 星期几
+        String chineseDayOfWeek = now.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.CHINA);
+        if ("星期一".equals(chineseDayOfWeek))
+            map.put("week", 1);
+        else if ("星期二".equals(chineseDayOfWeek))
+            map.put("week", 2);
+        else if ("星期三".equals(chineseDayOfWeek))
+            map.put("week", 3);
+        else if ("星期四".equals(chineseDayOfWeek))
+            map.put("week", 4);
+        else if ("星期五".equals(chineseDayOfWeek))
+            map.put("week", 5);
+        else if ("星期六".equals(chineseDayOfWeek))
+            map.put("week", 6);
+        else
+            map.put("week", 7);
+
+        // 分割年月日
+        String[] sDate = startDate.split("-");
+        LocalDate firstDayOfSemester = LocalDate.of(Integer.parseInt(sDate[0]), Integer.parseInt(sDate[1]), Integer.parseInt(sDate[2]));
+        LocalDate dateToCheck = LocalDate.of(year, month, day);
+        // 根据两个时间算出第几周
+        int weeks = (int) ((dateToCheck.toEpochDay() - firstDayOfSemester.toEpochDay()) / 7) + 1;
+        map.put("weeks", weeks);
+
+        return map;
+    }
+
+
+    /**
+     * 比较时间
+     *
+     * @param stime
+     * @param etime
+     * @return
+     */
+    public boolean campareTime(String stime, String etime) {
+        LocalDateTime now = LocalDateTime.now();
+        int h = now.getHour();
+        int m = now.getMinute();
+
+        String[] sTime = stime.split(":");
+        String[] eTime = etime.split(":");
+
+        // 指定开始时间
+        LocalTime startTime = LocalTime.of(Integer.parseInt(sTime[0]), Integer.parseInt(sTime[1]));
+        // 指定结束时间
+        LocalTime endTime = LocalTime.of(Integer.parseInt(eTime[0]), Integer.parseInt(eTime[1]));
+        // 现在时间
+        LocalTime timeToCheck = LocalTime.of(h, m);
+
+        return timeToCheck.isAfter(startTime) && timeToCheck.isBefore(endTime);
+    }
+}

+ 62 - 0
src/main/java/com/chuanghai/video/util/DbUtil.java

@@ -0,0 +1,62 @@
+package com.chuanghai.video.util;
+
+import java.sql.*;
+
+public class DbUtil {
+
+    private static final String URL = "jdbc:mysql://111.231.169.217:3306/smart_middle?useUnicode=tru&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true&allowPublicKeyRetrieval=true&allowMultiQueries=true&rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai";
+    private static final String USERNAME = "root";
+    private static final String PASSWORD = "Chuanghai2023.";
+
+    private static Connection getConnection() throws SQLException {
+        return DriverManager.getConnection(URL, USERNAME, PASSWORD);
+    }
+
+    public ResultSet executeQuery(String sql) {
+        Connection conn = null;
+        PreparedStatement stmt = null;
+        ResultSet rs = null;
+        try {
+            conn = getConnection();
+            stmt = conn.prepareStatement(sql);
+            rs = stmt.executeQuery();
+        } catch (SQLException e) {
+            e.printStackTrace();
+        } finally {
+            closeResultSet(rs);
+            closeStatement(stmt);
+            closeConnection(conn);
+        }
+        return rs;
+    }
+
+    public static void closeConnection(Connection conn) {
+        if (conn != null) {
+            try {
+                conn.close();
+            } catch (SQLException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public static void closeStatement(Statement stmt) {
+        if (stmt != null) {
+            try {
+                stmt.close();
+            } catch (SQLException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public static void closeResultSet(ResultSet rs) {
+        if (rs != null) {
+            try {
+                rs.close();
+            } catch (SQLException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+}

+ 62 - 0
src/main/java/com/chuanghai/video/util/JwtUtil.java

@@ -0,0 +1,62 @@
+package com.chuanghai.video.util;
+
+import com.chuanghai.video.entity.Admin;
+import io.jsonwebtoken.ExpiredJwtException;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+@Component
+public class JwtUtil {
+    private final String SECRET_KEY = "ch!@#123";
+
+    @Value("${myapp.mypre}")
+    private String prefix;
+
+    public String generateToken(String username) {
+        // 7天的有效期
+        long EXPIRATION_TIME = 7 * 24 * 60 * 60 * 1000;
+        Date now = new Date();
+        Date expiryDate = new Date(now.getTime() + EXPIRATION_TIME); // token期限
+        String token = Jwts.builder()
+                .setSubject(username)
+                .setIssuedAt(now)
+                .setExpiration(expiryDate)
+                .signWith(SignatureAlgorithm.HS512, SECRET_KEY)
+                .compact();
+        return prefix + token;
+    }
+
+    public String getUsernameFromToken(String token) {
+        try {
+            return Jwts.parser()
+                    .setSigningKey(SECRET_KEY)
+                    .parseClaimsJws(token)
+                    .getBody()
+                    .getSubject();
+        } catch (ExpiredJwtException e) {
+            return "";
+        }
+    }
+
+    public boolean validateToken(String token, Admin admin) {
+        String username = getUsernameFromToken(token);
+        return (username.equals(admin.getUsername()) && !isTokenExpired(token));
+    }
+
+    private boolean isTokenExpired(String token) {
+        try {
+            Date expiryDate = Jwts.parser()
+                    .setSigningKey(SECRET_KEY)
+                    .parseClaimsJws(token)
+                    .getBody()
+                    .getExpiration();
+            return expiryDate.before(new Date());
+        } catch (ExpiredJwtException e) {
+            return false;
+        }
+    }
+}

+ 218 - 0
src/main/java/com/chuanghai/video/util/OkHttpUtils.java

@@ -0,0 +1,218 @@
+package com.chuanghai.video.util;
+
+import okhttp3.*;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+public class OkHttpUtils {
+    private static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
+    private static final MediaType FORM_DATA = MediaType.get("multipart/form-data; charset=utf-8");
+    private static final MediaType PLAIN_TEXT = MediaType.get("text/plain; charset=utf-8");
+    private final OkHttpClient client = new OkHttpClient();
+
+    public CompletableFuture<String> makeAsyncRequest(String url) {
+        Request request = new Request.Builder()
+                .url(url)
+                .build();
+
+        CompletableFuture<String> future = new CompletableFuture<>();
+
+        client.newCall(request).enqueue(new Callback() {
+            @Override
+            public void onFailure(@NotNull Call call, IOException e) {
+                future.completeExceptionally(e);
+            }
+
+            @Override
+            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
+                String responseBody = null;
+                if (response.body() != null) {
+                    responseBody = response.body().string();
+                }
+                future.complete(responseBody);
+            }
+        });
+
+        return future;
+
+//        CompletableFuture<String> futureResult = myService.makeAsyncRequest();
+//
+//        try {
+//            String result = futureResult.get();
+//            System.out.println("Async request result: " + result);
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+    }
+
+    public String get(String url) {
+        Request request = new Request.Builder()
+                .url(url)
+                .build();
+        try (Response response = client.newCall(request).execute()) {
+            if (response.body() != null) {
+                return response.body().string();
+            } else {
+                return "";
+            }
+        } catch (IOException e) {
+            return e.getMessage();
+        }
+    }
+
+    public String get(String url, Map<String, String> params) {
+        HttpUrl httpUrl = HttpUrl.parse(url);
+        if (httpUrl == null) {
+            return "URL解析异常!";
+        }
+        HttpUrl.Builder httpBuilder = httpUrl.newBuilder();
+        for (Map.Entry<String, String> entry : params.entrySet()) {
+            httpBuilder.addQueryParameter(entry.getKey(), entry.getValue());
+        }
+        String newUrl = httpBuilder.build().toString();
+
+        Request request = new Request.Builder()
+                .url(newUrl)
+                .build();
+        try (Response response = client.newCall(request).execute()) {
+            if (response.body() != null) {
+                return response.body().string();
+            } else {
+                return "返回null";
+            }
+        } catch (IOException e) {
+            return e.getMessage();
+        }
+    }
+
+    public String post(String url, Map<String,String> headers) {
+        RequestBody body = RequestBody.create("", JSON);
+
+        Request.Builder requestBuilder = new Request.Builder()
+                .url(url)
+                .header("Content-Type", "application/json")
+                .post(body);
+
+        requestBuilder.addHeader("Content-Type", "application/json");
+        for (Map.Entry<String, String> entry : headers.entrySet()) {
+            requestBuilder.addHeader(entry.getKey(), entry.getValue());
+        }
+
+        Request request = requestBuilder.build();
+
+        try (Response response = client.newCall(request).execute()) {
+            if (response.body() != null) {
+                return response.body().string();
+            } else {
+                return "返回null";
+            }
+        } catch (IOException e) {
+            return e.getMessage();
+        }
+    }
+
+    public String postJson(String url, String json, Map<String,String> headers) {
+        RequestBody body = RequestBody.create(json, JSON);
+
+        Request.Builder requestBuilder = new Request.Builder()
+                .url(url)
+                .post(body);
+
+        requestBuilder.addHeader("Content-Type", "application/json");
+        for (Map.Entry<String, String> entry : headers.entrySet()) {
+            requestBuilder.addHeader(entry.getKey(), entry.getValue());
+        }
+
+        Request request = requestBuilder.build();
+
+        try (Response response = client.newCall(request).execute()) {
+            if (response.body() != null) {
+                return response.body().string();
+            } else {
+                return "返回null";
+            }
+        } catch (IOException e) {
+            return e.getMessage();
+        }
+    }
+
+    public String postFormData(String url, Map<String, String> formData, Map<String, String> headers) {
+        MultipartBody.Builder formBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);
+        for (Map.Entry<String, String> entry : formData.entrySet()) {
+            formBuilder.addFormDataPart(entry.getKey(), entry.getValue());
+        }
+
+        RequestBody formBody = formBuilder.build();
+
+        Request.Builder requestBuilder = new Request.Builder()
+                .url(url)
+                .post(formBody);
+
+        requestBuilder.addHeader("Content-Type", "multipart/form-data");
+        for (Map.Entry<String, String> entry : headers.entrySet()) {
+            requestBuilder.addHeader(entry.getKey(), entry.getValue());
+        }
+
+        Request request = requestBuilder.build();
+        try (Response response = client.newCall(request).execute()) {
+            if (response.body() != null) {
+                return response.body().string();
+            } else {
+                return "返回null";
+            }
+        } catch (IOException e) {
+            return e.getMessage();
+        }
+    }
+
+    public String postPlainText(String url, String text) {
+        RequestBody body = RequestBody.create(text, PLAIN_TEXT);
+
+        Request request = new Request.Builder()
+                .url(url)
+                .header("Content-Type", "text/plain")
+                .post(body)
+                .build();
+        try (Response response = client.newCall(request).execute()) {
+            if (response.body() != null) {
+                return response.body().string();
+            } else {
+                return "";
+            }
+        } catch (IOException e) {
+            return e.getMessage();
+        }
+    }
+
+    public String postJsonFormDataPlainText(String url, Map<String, String> formData, Map<String, String> jsonParams, Map<String, String> textParams) {
+        MultipartBody.Builder formBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);
+        for (Map.Entry<String, String> entry : formData.entrySet()) {
+            formBuilder.addFormDataPart(entry.getKey(), entry.getValue());
+        }
+        for (Map.Entry<String, String> entry : jsonParams.entrySet()) {
+            formBuilder.addFormDataPart(entry.getKey(), entry.getValue(), RequestBody.create(entry.getValue(), JSON));
+        }
+        for (Map.Entry<String, String> entry : textParams.entrySet()) {
+            formBuilder.addFormDataPart(entry.getKey(), entry.getValue(), RequestBody.create(entry.getValue(), PLAIN_TEXT));
+        }
+        RequestBody formBody = formBuilder.build();
+
+        Request request = new Request.Builder()
+                .url(url)
+                .header("Content-Type", "multipart/form-data")
+                .post(formBody)
+                .build();
+        try (Response response = client.newCall(request).execute()) {
+            if (response.body() != null) {
+                return response.body().string();
+            } else {
+                return "";
+            }
+        } catch (IOException e) {
+            return e.getMessage();
+        }
+    }
+}

+ 43 - 0
src/main/java/com/chuanghai/video/util/PasswordEncryptionUtil.java

@@ -0,0 +1,43 @@
+package com.chuanghai.video.util;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class PasswordEncryptionUtil {
+    final static String salt = "ch!@#qwe";
+
+    public static String md5Hash(String password) {
+        String input = password + salt;
+        StringBuilder md5Hash = new StringBuilder();
+
+        try {
+            MessageDigest md = MessageDigest.getInstance("MD5");
+            byte[] messageDigest = md.digest(input.getBytes());
+
+            for (byte b : messageDigest) {
+                md5Hash.append(String.format("%02x", b));
+            }
+        } catch (NoSuchAlgorithmException e) {
+            System.out.println(e.getMessage());
+        }
+
+        return md5Hash.toString();
+    }
+
+    public static String sha2Hash(String input) {
+        StringBuilder sha2Hash = new StringBuilder();
+
+        try {
+            MessageDigest md = MessageDigest.getInstance("SHA-256");
+            byte[] messageDigest = md.digest(input.getBytes());
+
+            for (byte b : messageDigest) {
+                sha2Hash.append(String.format("%02x", b));
+            }
+        } catch (NoSuchAlgorithmException e) {
+            System.out.println(e.getMessage());
+        }
+
+        return sha2Hash.toString();
+    }
+}

+ 59 - 0
src/main/resources/application.yml

@@ -0,0 +1,59 @@
+server:
+  port: 8083
+  session:
+    timeout: 1440m
+  servlet:
+    context-path: /av_ja
+  tomcat:
+    uri-encoding: UTF-8
+    max-threads: 1000
+    max-http-header-size: 102400
+
+spring:
+  application:
+    name: transcoding
+  main:
+    allow-circular-references: true
+  datasource:
+    username: root
+    password: UUtfNu3jVQy3ZA@#
+#    username: root
+#    password: 123456
+    url: jdbc:mysql://localhost:3306/video_wzsz?characterEncoding=UTF-8&useSSL=false&useUnicode=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    #spring官方推荐 性能最强,没有之一
+    hikari:
+      pool-name: Retail_HikariCP
+      minimum-idle: 5 #最小空闲连接数量
+      idle-timeout: 30000 #空闲连接存活最大时间,默认600000(10分钟)
+      maximum-pool-size: 10 #连接池最大连接数,默认是10
+      auto-commit: true  #此属性控制从池返回的连接的默认自动提交行为,默认值:true
+      max-lifetime: 120000 #此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
+      connection-timeout: 30000 #数据库连接超时时间,默认30秒,即30000
+      connection-test-query: SELECT 1
+  jackson:
+    date-format: yyyy-MM-dd HH:mm:ss
+    time-zone: GMT+8
+#    default-property-inclusion: non_null
+  devtools:
+    restart:
+      enabled: true
+    additional-paths: src/main/java
+
+#分页pageHelper
+pagehelper:
+  helperDialect: mysql
+  reasonable: true  #为了使用输入页数为负或者超出最大页时候使页数为最小或最大值
+  supportMethodsArguments: true
+  params: count=countSql
+  pageSizeZero: true
+
+mybatis-plus:
+  # spring boot集成mybatis的方式打印sql
+  configuration:
+#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+    #关闭sql打印
+    log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl
+
+myapp:
+  mypre: VIDEO

+ 83 - 0
src/main/resources/sql/video.sql

@@ -0,0 +1,83 @@
+/*
+ Navicat Premium Data Transfer
+
+ Source Server         : 172.16.20.75视频流数据库
+ Source Server Type    : MySQL
+ Source Server Version : 80024
+ Source Host           : 172.16.20.75:3306
+ Source Schema         : video
+
+ Target Server Type    : MySQL
+ Target Server Version : 80024
+ File Encoding         : 65001
+
+ Date: 04/01/2024 11:07:40
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for video_admin
+-- ----------------------------
+DROP TABLE IF EXISTS `video_admin`;
+CREATE TABLE `video_admin`  (
+  `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT 'id',
+  `username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名',
+  `phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '手机号码',
+  `admin_type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '角色类别,1超级管理员、2普通管理员',
+  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码 登录密码',
+  `authority` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '权限数组',
+  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
+  `statu` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '状态 0冻结、1正常',
+  `sex` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '性别1(男)0(女)',
+  `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '姓名',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE INDEX `phone_unique_index`(`phone`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1633663056028422147 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '酒店管理员' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for video_camera
+-- ----------------------------
+DROP TABLE IF EXISTS `video_camera`;
+CREATE TABLE `video_camera`  (
+  `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `online` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否在线  1(在线)  0(离线)',
+  `unit_type` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '设备型号',
+  `vendor` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '厂商',
+  `agreement` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '协议',
+  `installation_site` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '安装位置',
+  `output_link` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '输出链接',
+  `camera_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '监控推流Key',
+  `ip` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '监控IP地址',
+  `ip_password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '监控IP密码',
+  `camera_coding` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '摄像头编码',
+  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
+  `creater` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '创建人',
+  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
+  `last_updater` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '最后更新人',
+  `last_update_time` datetime(0) NULL DEFAULT NULL COMMENT '最后更新时间',
+  `statu` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '使用状态  1(使用) 0(停用)',
+  `mp_link` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'MP4播放链接',
+  `hls_link` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'hls播放链接',
+  `ts_link` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'ts播放链接',
+  `flv_link` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'flv播放链接',
+  `now_line` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '当前播放路线',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE INDEX `ipUnique`(`ip`) USING BTREE COMMENT 'IP唯一'
+) ENGINE = InnoDB AUTO_INCREMENT = 993 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for video_player
+-- ----------------------------
+DROP TABLE IF EXISTS `video_player`;
+CREATE TABLE `video_player`  (
+  `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `ip` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'ip地址',
+  `player_count` int(0) NULL DEFAULT NULL COMMENT '当前ip播放人数',
+  `line` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '播放线路',
+  `vendor` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '监控厂商',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1740669394729607171 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
+
+SET FOREIGN_KEY_CHECKS = 1;

BIN
src/main/resources/static/监控信息导入格式要求.xls


+ 13 - 0
src/test/java/com/chuanghai/video/VideoTranscodingApplicationTests.java

@@ -0,0 +1,13 @@
+package com.chuanghai.video;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class VideoTranscodingApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}

+ 59 - 0
target/classes/application.yml

@@ -0,0 +1,59 @@
+server:
+  port: 8083
+  session:
+    timeout: 1440m
+  servlet:
+    context-path: /av_ja
+  tomcat:
+    uri-encoding: UTF-8
+    max-threads: 1000
+    max-http-header-size: 102400
+
+spring:
+  application:
+    name: transcoding
+  main:
+    allow-circular-references: true
+  datasource:
+    username: root
+    password: UUtfNu3jVQy3ZA@#
+#    username: root
+#    password: 123456
+    url: jdbc:mysql://localhost:3306/video_wzsz?characterEncoding=UTF-8&useSSL=false&useUnicode=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    #spring官方推荐 性能最强,没有之一
+    hikari:
+      pool-name: Retail_HikariCP
+      minimum-idle: 5 #最小空闲连接数量
+      idle-timeout: 30000 #空闲连接存活最大时间,默认600000(10分钟)
+      maximum-pool-size: 10 #连接池最大连接数,默认是10
+      auto-commit: true  #此属性控制从池返回的连接的默认自动提交行为,默认值:true
+      max-lifetime: 120000 #此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
+      connection-timeout: 30000 #数据库连接超时时间,默认30秒,即30000
+      connection-test-query: SELECT 1
+  jackson:
+    date-format: yyyy-MM-dd HH:mm:ss
+    time-zone: GMT+8
+#    default-property-inclusion: non_null
+  devtools:
+    restart:
+      enabled: true
+    additional-paths: src/main/java
+
+#分页pageHelper
+pagehelper:
+  helperDialect: mysql
+  reasonable: true  #为了使用输入页数为负或者超出最大页时候使页数为最小或最大值
+  supportMethodsArguments: true
+  params: count=countSql
+  pageSizeZero: true
+
+mybatis-plus:
+  # spring boot集成mybatis的方式打印sql
+  configuration:
+#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+    #关闭sql打印
+    log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl
+
+myapp:
+  mypre: VIDEO

+ 83 - 0
target/classes/sql/video.sql

@@ -0,0 +1,83 @@
+/*
+ Navicat Premium Data Transfer
+
+ Source Server         : 172.16.20.75视频流数据库
+ Source Server Type    : MySQL
+ Source Server Version : 80024
+ Source Host           : 172.16.20.75:3306
+ Source Schema         : video
+
+ Target Server Type    : MySQL
+ Target Server Version : 80024
+ File Encoding         : 65001
+
+ Date: 04/01/2024 11:07:40
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for video_admin
+-- ----------------------------
+DROP TABLE IF EXISTS `video_admin`;
+CREATE TABLE `video_admin`  (
+  `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT 'id',
+  `username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名',
+  `phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '手机号码',
+  `admin_type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '角色类别,1超级管理员、2普通管理员',
+  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码 登录密码',
+  `authority` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '权限数组',
+  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
+  `statu` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '状态 0冻结、1正常',
+  `sex` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '性别1(男)0(女)',
+  `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '姓名',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE INDEX `phone_unique_index`(`phone`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1633663056028422147 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '酒店管理员' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for video_camera
+-- ----------------------------
+DROP TABLE IF EXISTS `video_camera`;
+CREATE TABLE `video_camera`  (
+  `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `online` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否在线  1(在线)  0(离线)',
+  `unit_type` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '设备型号',
+  `vendor` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '厂商',
+  `agreement` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '协议',
+  `installation_site` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '安装位置',
+  `output_link` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '输出链接',
+  `camera_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '监控推流Key',
+  `ip` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '监控IP地址',
+  `ip_password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '监控IP密码',
+  `camera_coding` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '摄像头编码',
+  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
+  `creater` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '创建人',
+  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
+  `last_updater` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '最后更新人',
+  `last_update_time` datetime(0) NULL DEFAULT NULL COMMENT '最后更新时间',
+  `statu` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '使用状态  1(使用) 0(停用)',
+  `mp_link` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'MP4播放链接',
+  `hls_link` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'hls播放链接',
+  `ts_link` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'ts播放链接',
+  `flv_link` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'flv播放链接',
+  `now_line` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '当前播放路线',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE INDEX `ipUnique`(`ip`) USING BTREE COMMENT 'IP唯一'
+) ENGINE = InnoDB AUTO_INCREMENT = 993 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for video_player
+-- ----------------------------
+DROP TABLE IF EXISTS `video_player`;
+CREATE TABLE `video_player`  (
+  `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `ip` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'ip地址',
+  `player_count` int(0) NULL DEFAULT NULL COMMENT '当前ip播放人数',
+  `line` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '播放线路',
+  `vendor` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '监控厂商',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1740669394729607171 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
+
+SET FOREIGN_KEY_CHECKS = 1;

BIN
target/classes/static/监控信息导入格式要求.xls


+ 3 - 0
target/maven-archiver/pom.properties

@@ -0,0 +1,3 @@
+artifactId=video_transcoding
+groupId=com.chuanghai
+version=0.0.1-SNAPSHOT

+ 30 - 0
target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst

@@ -0,0 +1,30 @@
+com\chuanghai\video\controller\AdminController.class
+com\chuanghai\video\entity\Admin.class
+com\chuanghai\video\util\OkHttpUtils.class
+com\chuanghai\video\util\DbUtil.class
+com\chuanghai\video\entity\Player.class
+com\chuanghai\video\util\DateTimeUtil.class
+com\chuanghai\video\util\OkHttpUtils$1.class
+com\chuanghai\video\controller\CameraController.class
+com\chuanghai\video\util\CommonUtil.class
+com\chuanghai\video\controller\VideoController.class
+com\chuanghai\video\core\ResponseStatus.class
+com\chuanghai\video\entity\Spot.class
+com\chuanghai\video\mapper\ConfigMapper.class
+com\chuanghai\video\mapper\SpotMapper.class
+com\chuanghai\video\core\ResponseResult$ResponseResultBuilder.class
+com\chuanghai\video\core\ResponseResult.class
+com\chuanghai\video\VideoTranscodingApplication.class
+com\chuanghai\video\controller\SpotController.class
+com\chuanghai\video\config\WebMvcConfig.class
+com\chuanghai\video\mapper\CameraMapper.class
+com\chuanghai\video\common\Common.class
+com\chuanghai\video\core\interceptor\JwtInterceptor.class
+com\chuanghai\video\entity\Camera.class
+com\chuanghai\video\controller\ConfigController.class
+com\chuanghai\video\mapper\VideoMapper.class
+com\chuanghai\video\entity\Config.class
+com\chuanghai\video\util\JwtUtil.class
+com\chuanghai\video\mapper\AdminMapper.class
+com\chuanghai\video\entity\CameraRelationship.class
+com\chuanghai\video\util\PasswordEncryptionUtil.class

+ 28 - 0
target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst

@@ -0,0 +1,28 @@
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\util\PasswordEncryptionUtil.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\util\DbUtil.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\controller\VideoController.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\core\ResponseResult.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\entity\Spot.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\config\WebMvcConfig.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\VideoTranscodingApplication.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\mapper\VideoMapper.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\mapper\ConfigMapper.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\entity\Admin.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\mapper\CameraMapper.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\entity\Camera.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\mapper\AdminMapper.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\controller\CameraController.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\mapper\SpotMapper.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\entity\CameraRelationship.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\entity\Config.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\util\JwtUtil.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\util\DateTimeUtil.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\controller\SpotController.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\entity\Player.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\util\CommonUtil.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\core\interceptor\JwtInterceptor.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\util\OkHttpUtils.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\common\Common.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\controller\ConfigController.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\controller\AdminController.java
+D:\E\各公司项目\video-api-wzsz\src\main\java\com\chuanghai\video\core\ResponseStatus.java

+ 1 - 0
target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst

@@ -0,0 +1 @@
+com\chuanghai\video\VideoTranscodingApplicationTests.class

+ 1 - 0
target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst

@@ -0,0 +1 @@
+D:\E\各公司项目\video-api-wzsz\src\test\java\com\chuanghai\video\VideoTranscodingApplicationTests.java

File diff suppressed because it is too large
+ 67 - 0
target/surefire-reports/TEST-com.chuanghai.video.VideoTranscodingApplicationTests.xml


+ 4 - 0
target/surefire-reports/com.chuanghai.video.VideoTranscodingApplicationTests.txt

@@ -0,0 +1,4 @@
+-------------------------------------------------------------------------------
+Test set: com.chuanghai.video.VideoTranscodingApplicationTests
+-------------------------------------------------------------------------------
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 6.698 s - in com.chuanghai.video.VideoTranscodingApplicationTests

BIN
target/videoApi_wzsz.jar.original


+ 8 - 0
video_transcoding.iml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4">
+  <component name="FacetManager">
+    <facet type="Spring" name="Spring">
+      <configuration />
+    </facet>
+  </component>
+</module>

BIN
监控信息导入格式要求.xls