commit 63c530c3ac798facb7749e375e8571b7849b5d3b
Author: sunyuchen <2425442416@qq.com>
Date: Fri May 8 19:15:39 2026 +0800
影像代码提交 -20260508
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..97444c6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,34 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+/target/*
diff --git a/README.en.md b/README.en.md
new file mode 100644
index 0000000..7eff1ec
--- /dev/null
+++ b/README.en.md
@@ -0,0 +1,25 @@
+# activate-video-service
+
+#### Software Architecture
+
+Software architecture description
+
+#### Installation
+
+1. xxxx
+2. xxxx
+3. xxxx
+
+#### Instructions
+
+1. xxxx
+2. xxxx
+3. xxxx
+
+#### Contribution
+
+1. Fork the repository
+2. Create Feat_xxx branch
+3. Commit your code
+4. Create Pull Request
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2c6888c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,22 @@
+# activate-video-service
+
+#### 介绍
+
+{以下是 Gitee 平台说明,您可以替换此简介 Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台。专为开发者提供稳定、高效、安全的云端软件开发协作平台 无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。}
+
+#### 软件架构
+
+软件架构说明
+
+#### 安装教程
+
+xxxx
+xxxx
+xxxx
+
+#### 使用说明
+
+xxxx
+xxxx
+xxxx
+
diff --git a/mvnw b/mvnw
new file mode 100644
index 0000000..8a8fb22
--- /dev/null
+++ b/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 "$@"
diff --git a/mvnw.cmd b/mvnw.cmd
new file mode 100644
index 0000000..1d8ab01
--- /dev/null
+++ b/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%
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..3b808a2
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,123 @@
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.7.16
+
+
+
+
+ 4.0.0
+ activate-video-service
+ Activate Video Download and View Service
+ com.gbg
+ activate-video-service
+ 0.0.1-SNAPSHOT
+ war
+
+
+
+ 1.8
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+ 2.3.1
+
+
+ org.springframework.session
+ spring-session-core
+
+
+ com.alibaba
+ druid-spring-boot-starter
+ 1.2.6
+
+
+ com.microsoft.sqlserver
+ mssql-jdbc
+ runtime
+
+
+ org.apache.commons
+ commons-lang3
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+ provided
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter-test
+ 2.3.1
+ test
+
+
+
+ org.springframework.boot
+ spring-boot-starter-quartz
+
+
+ org.apache.tika
+ tika-core
+ 2.4.1
+
+
+ org.apache.tika
+ tika-parsers-standard-package
+ 2.4.1
+
+
+ com.icms.sdk
+ icms-image-sdk
+ 1.0.28
+
+
+ com.cmbc.sg
+ sg-client-impl
+
+
+
+
+
+ com.cmbc.sg
+ sg-client-impl
+ 2.3.1.4
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/gbg/activate/video/ActivateVideoApplication.java b/src/main/java/com/gbg/activate/video/ActivateVideoApplication.java
new file mode 100644
index 0000000..cce201e
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/ActivateVideoApplication.java
@@ -0,0 +1,13 @@
+package com.gbg.activate.video;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class ActivateVideoApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ActivateVideoApplication.class, args);
+ }
+
+}
diff --git a/src/main/java/com/gbg/activate/video/ServletInitializer.java b/src/main/java/com/gbg/activate/video/ServletInitializer.java
new file mode 100644
index 0000000..d47006e
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/ServletInitializer.java
@@ -0,0 +1,13 @@
+package com.gbg.activate.video;
+
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+public class ServletInitializer extends SpringBootServletInitializer {
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(ActivateVideoApplication.class);
+ }
+
+}
diff --git a/src/main/java/com/gbg/activate/video/config/DownloadSchedulerConfig.java b/src/main/java/com/gbg/activate/video/config/DownloadSchedulerConfig.java
new file mode 100644
index 0000000..6270b5a
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/config/DownloadSchedulerConfig.java
@@ -0,0 +1,93 @@
+package com.gbg.activate.video.config;
+
+import com.gbg.activate.video.job.AudioFileCleanupJob;
+import com.gbg.activate.video.job.RecordingDownloadJob;
+import org.quartz.CronScheduleBuilder;
+import org.quartz.JobBuilder;
+import org.quartz.JobDetail;
+import org.quartz.Trigger;
+import org.quartz.TriggerBuilder;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.gbg.activate.video.job.ClearExpiredFileJob;
+import com.gbg.activate.video.job.VideoDownloadJob;
+
+@Configuration
+public class DownloadSchedulerConfig {
+ @Value("${download.cron}")
+ private String downloadCron;
+ @Value("${clear-expired.cron}")
+ private String clearExpiredCron;
+ @Value("${clean-audio.cron}")
+ private String cleanupAudioCron;
+
+ @Bean
+ public JobDetail downloadJobDetail() {
+ return JobBuilder.newJob(VideoDownloadJob.class)
+ .withIdentity("VideoDownloadJob", "VideoGroup")
+ .storeDurably()
+ .build();
+ }
+
+ @Bean
+ public Trigger downloadJobTrigger() {
+ return TriggerBuilder.newTrigger()
+ .forJob(downloadJobDetail())
+ .withIdentity("VideoDownloadTrigger", "VideoGroup")
+ .withSchedule(CronScheduleBuilder.cronSchedule(downloadCron)) // 每5分钟执行一次
+ .build();
+ }
+
+ @Bean
+ public JobDetail clearExpiredFileJobDetail() {
+ return JobBuilder.newJob(ClearExpiredFileJob.class)
+ .withIdentity("ClearExpiredFileJob", "VideoGroup")
+ .storeDurably()
+ .build();
+ }
+
+ @Bean
+ public Trigger clearExpiredFileJobTrigger() {
+ return TriggerBuilder.newTrigger()
+ .forJob(clearExpiredFileJobDetail())
+ .withIdentity("ClearExpiredFileTrigger", "VideoGroup")
+ .withSchedule(CronScheduleBuilder.cronSchedule(clearExpiredCron)) // 每5分钟执行一次
+ .build();
+ }
+
+ @Bean
+ public JobDetail downloadRecordingJobDetail() {
+ return JobBuilder.newJob(RecordingDownloadJob.class)
+ .withIdentity("downloadRecordingJobDetail", "VideoGroup")
+ .storeDurably()
+ .build();
+ }
+
+ @Bean
+ public Trigger downloadJobRecordingTrigger() {
+ return TriggerBuilder.newTrigger()
+ .forJob(downloadRecordingJobDetail())
+ .withIdentity("downloadJobRecordingTrigger", "VideoGroup")
+ .withSchedule(CronScheduleBuilder.cronSchedule(downloadCron)) // 每5分钟执行一次
+ .build();
+ }
+
+ @Bean
+ public JobDetail cleanAudioJobDetail() {
+ return JobBuilder.newJob(AudioFileCleanupJob.class)
+ .withIdentity("cleanAudioJobDetail", "VideoGroup")
+ .storeDurably()
+ .build();
+ }
+
+ @Bean
+ public Trigger cleanupAudioTrigger() {
+ return TriggerBuilder.newTrigger()
+ .forJob(downloadRecordingJobDetail())
+ .withIdentity("cleanupAudioTrigger", "VideoGroup")
+ .withSchedule(CronScheduleBuilder.cronSchedule(cleanupAudioCron)) // 每天凌晨3点执行
+ .build();
+ }
+}
diff --git a/src/main/java/com/gbg/activate/video/config/DruidConfig.java b/src/main/java/com/gbg/activate/video/config/DruidConfig.java
new file mode 100644
index 0000000..de0909d
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/config/DruidConfig.java
@@ -0,0 +1,18 @@
+package com.gbg.activate.video.config;
+
+import javax.sql.DataSource;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.alibaba.druid.pool.DruidDataSource;
+
+@Configuration
+public class DruidConfig {
+ @ConfigurationProperties(prefix = "spring.datasource")
+ @Bean(destroyMethod = "") // 避免 Tomcat 重启时多次关闭数据源报错的问题
+ public DataSource druidDataSource() {
+ return new DruidDataSource();
+ }
+}
diff --git a/src/main/java/com/gbg/activate/video/config/GBGBase64Utils.java b/src/main/java/com/gbg/activate/video/config/GBGBase64Utils.java
new file mode 100644
index 0000000..f172f07
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/config/GBGBase64Utils.java
@@ -0,0 +1,16 @@
+package com.gbg.activate.video.config;
+
+import java.util.Base64;
+
+public class GBGBase64Utils {
+ private GBGBase64Utils() {
+ }
+
+ public static String decode(String encodedString) {
+ return new String(Base64.getDecoder().decode(encodedString));
+ }
+
+ public static String encode(String originalInput) {
+ return Base64.getEncoder().encodeToString(originalInput.getBytes());
+ }
+}
diff --git a/src/main/java/com/gbg/activate/video/config/GBGDruidPasswordCallback.java b/src/main/java/com/gbg/activate/video/config/GBGDruidPasswordCallback.java
new file mode 100644
index 0000000..e4a4738
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/config/GBGDruidPasswordCallback.java
@@ -0,0 +1,28 @@
+package com.gbg.activate.video.config;
+
+import java.util.Properties;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.alibaba.druid.util.DruidPasswordCallback;
+
+public class GBGDruidPasswordCallback extends DruidPasswordCallback {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void setProperties(Properties properties) {
+ super.setProperties(properties);
+ // 获取配置文件中的已经加密的密码(spring.datasource.druid.connect-properties.password)
+ // 若不配置 connect-properties.password ,则默认使用的 spring.datasource(.druid).password 的属性值
+ String encodedPassword = (String) properties.get("password");
+ if (StringUtils.isNotEmpty(encodedPassword)) {
+ try {
+ // 这里的代码是将密码进行解密,并设置
+ String password = GBGBase64Utils.decode(encodedPassword);
+ setPassword(password.toCharArray());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/gbg/activate/video/config/ImageSdkConfig.java b/src/main/java/com/gbg/activate/video/config/ImageSdkConfig.java
new file mode 100644
index 0000000..c817d2a
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/config/ImageSdkConfig.java
@@ -0,0 +1,21 @@
+package com.gbg.activate.video.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.icms.sdk.bean.SdkConfig;
+import com.icms.sdk.impl.ImageSdkImpl;
+import com.icms.sdk.inter.ImageSdkInter;
+
+@Configuration
+public class ImageSdkConfig {
+ @Autowired
+ private ImageSdkParams params;
+
+ @Bean(name = "imageService")
+ public ImageSdkInter initImageSdk() {
+ SdkConfig config = new SdkConfig(params.getIcmsF5Ip(), params.getWmNo(), params.getcTime(), params.getrTime());
+ return new ImageSdkImpl(config);
+ }
+}
diff --git a/src/main/java/com/gbg/activate/video/config/ImageSdkParams.java b/src/main/java/com/gbg/activate/video/config/ImageSdkParams.java
new file mode 100644
index 0000000..0d9be24
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/config/ImageSdkParams.java
@@ -0,0 +1,94 @@
+package com.gbg.activate.video.config;
+
+import java.io.Serializable;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConfigurationProperties(prefix="image-sdk")
+public class ImageSdkParams implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private String icmsF5Ip;
+ private String wmNo;
+ private String cTime;
+ private String rTime;
+ private String sysNo;
+ private String fileSavePath;
+ private Integer validDays;
+ private String sysNo1;
+ private String fileSavePath1;
+
+ public String getIcmsF5Ip() {
+ return icmsF5Ip;
+ }
+
+ public void setIcmsF5Ip(String icmsF5Ip) {
+ this.icmsF5Ip = icmsF5Ip;
+ }
+
+ public String getWmNo() {
+ return wmNo;
+ }
+
+ public void setWmNo(String wmNo) {
+ this.wmNo = wmNo;
+ }
+
+ public String getcTime() {
+ return cTime;
+ }
+
+ public void setcTime(String cTime) {
+ this.cTime = cTime;
+ }
+
+ public String getrTime() {
+ return rTime;
+ }
+
+ public void setrTime(String rTime) {
+ this.rTime = rTime;
+ }
+
+ public String getSysNo() {
+ return sysNo;
+ }
+
+ public void setSysNo(String sysNo) {
+ this.sysNo = sysNo;
+ }
+
+ public String getFileSavePath() {
+ return fileSavePath;
+ }
+
+ public void setFileSavePath(String fileSavePath) {
+ this.fileSavePath = fileSavePath;
+ }
+
+ public Integer getValidDays() {
+ return validDays;
+ }
+
+ public void setValidDays(Integer validDays) {
+ this.validDays = validDays;
+ }
+
+ public String getSysNo1() {
+ return sysNo1;
+ }
+
+ public void setSysNo1(String sysNo1) {
+ this.sysNo1 = sysNo1;
+ }
+
+ public String getFileSavePath1() {
+ return fileSavePath1;
+ }
+
+ public void setFileSavePath1(String fileSavePath1) {
+ this.fileSavePath1 = fileSavePath1;
+ }
+}
diff --git a/src/main/java/com/gbg/activate/video/constant/DownloadStatus.java b/src/main/java/com/gbg/activate/video/constant/DownloadStatus.java
new file mode 100644
index 0000000..0d125a4
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/constant/DownloadStatus.java
@@ -0,0 +1,23 @@
+package com.gbg.activate.video.constant;
+
+public interface DownloadStatus {
+ /**
+ * PENDING 等待下载
+ */
+ String PENDING = "PENDING";
+
+ /**
+ * DOWNLOADING 正在下载
+ */
+ String DOWNLOADING = "DOWNLOADING";
+
+ /**
+ * COMPLETED 下载完成
+ */
+ String COMPLETED = "COMPLETED";
+
+ /**
+ * FAILED 下载失败
+ */
+ String FAILED = "FAILED";
+}
diff --git a/src/main/java/com/gbg/activate/video/controller/RecordingViewController.java b/src/main/java/com/gbg/activate/video/controller/RecordingViewController.java
new file mode 100644
index 0000000..5be589e
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/controller/RecordingViewController.java
@@ -0,0 +1,47 @@
+package com.gbg.activate.video.controller;
+
+import com.gbg.activate.video.service.IRecordingViewService;
+import com.gbg.activate.video.service.IVideoViewService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.MediaTypeFactory;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.net.MalformedURLException;
+
+@RestController
+public class RecordingViewController {
+ @Autowired
+ private IRecordingViewService recordingViewService;
+
+ /**
+ * @Title: viewFile
+ * @Description: 查看视频文件
+ * @param fileName
+ * @return 参数
+ * @return ResponseEntity 返回类型
+ * @throws
+ * @author Frank.Wang@gbgplc.com
+ * @date 2025-07-16 03:18:06
+ */
+ @GetMapping("/recording/{fileName:.+}")
+ public ResponseEntity viewFile(@PathVariable String fileName) {
+ try {
+ Resource resource = recordingViewService.viewFile(fileName);
+ if (!resource.exists() || !resource.isReadable()) {
+ return ResponseEntity.notFound().build();
+ }
+ return ResponseEntity.ok()
+ .contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM))
+ .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
+ .body(resource);
+ } catch (MalformedURLException e) {
+ return ResponseEntity.notFound().build();
+ }
+ }
+}
diff --git a/src/main/java/com/gbg/activate/video/controller/VideoViewController.java b/src/main/java/com/gbg/activate/video/controller/VideoViewController.java
new file mode 100644
index 0000000..310e158
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/controller/VideoViewController.java
@@ -0,0 +1,47 @@
+package com.gbg.activate.video.controller;
+
+import java.net.MalformedURLException;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.MediaTypeFactory;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.gbg.activate.video.service.IVideoViewService;
+
+@RestController
+public class VideoViewController {
+ @Autowired
+ private IVideoViewService videoViewService;
+
+ /**
+ * @Title: viewFile
+ * @Description: 查看视频文件
+ * @param fileName
+ * @return 参数
+ * @return ResponseEntity 返回类型
+ * @throws
+ * @author Frank.Wang@gbgplc.com
+ * @date 2025-07-16 03:18:06
+ */
+ @GetMapping("/videos/{fileName:.+}")
+ public ResponseEntity viewFile(@PathVariable String fileName) {
+ try {
+ Resource resource = videoViewService.viewFile(fileName);
+ if (!resource.exists() || !resource.isReadable()) {
+ return ResponseEntity.notFound().build();
+ }
+ return ResponseEntity.ok()
+ .contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM))
+ .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
+ .body(resource);
+ } catch (MalformedURLException e) {
+ return ResponseEntity.notFound().build();
+ }
+ }
+}
diff --git a/src/main/java/com/gbg/activate/video/entity/RecordingDownloadDO.java b/src/main/java/com/gbg/activate/video/entity/RecordingDownloadDO.java
new file mode 100644
index 0000000..f760db5
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/entity/RecordingDownloadDO.java
@@ -0,0 +1,203 @@
+package com.gbg.activate.video.entity;
+
+import java.io.Serializable;
+import java.util.Date;
+
+public class RecordingDownloadDO implements Serializable {
+ /**
+ * @Fields Application_Number 申请编号
+ */
+ private String applicationNumber;
+
+ /**
+ * @Fields Call_Id 通话编号
+ */
+ private String callId;
+
+ /**
+ * @Fields Image_Id 唯一编号
+ */
+ private String imageId;
+
+ /**
+ * @Fields Image_Name 文件名称
+ */
+ private String imageName;
+
+ /**
+ * @Fields Image_Type 文件类型
+ */
+ private String imageType;
+
+ /**
+ * @Fields Image_Size 文件大小
+ */
+ private String imageSize;
+
+ /**
+ * @Fields Image_Url 文件下载链接
+ */
+ private String imageUrl;
+
+ /**
+ * @Fields Create_Time 创建时间
+ */
+ private String createTime;
+
+ /**
+ * @Fields Download_Time 下载时间
+ */
+ private Date downloadTime;
+
+ /**
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database table Video_Signing_Download_Record
+ *
+ * @mbg.generated
+ */
+ private static final long serialVersionUID = 1L;
+
+ public String getApplicationNumber() {
+ return applicationNumber;
+ }
+
+ public void setApplicationNumber(String applicationNumber) {
+ this.applicationNumber = applicationNumber == null ? null : applicationNumber.trim();
+ }
+
+ public String getCallId() {
+ return callId;
+ }
+
+ public void setCallId(String callId) {
+ this.callId = callId == null ? null : callId.trim();
+ }
+
+ public String getImageId() {
+ return imageId;
+ }
+
+ public void setImageId(String imageId) {
+ this.imageId = imageId == null ? null : imageId.trim();
+ }
+
+ public String getImageName() {
+ return imageName;
+ }
+
+ public void setImageName(String imageName) {
+ this.imageName = imageName == null ? null : imageName.trim();
+ }
+
+ public String getImageType() {
+ return imageType;
+ }
+
+ public void setImageType(String imageType) {
+ this.imageType = imageType == null ? null : imageType.trim();
+ }
+
+ public String getImageSize() {
+ return imageSize;
+ }
+
+ public void setImageSize(String imageSize) {
+ this.imageSize = imageSize == null ? null : imageSize.trim();
+ }
+
+ public String getImageUrl() {
+ return imageUrl;
+ }
+
+ public void setImageUrl(String imageUrl) {
+ this.imageUrl = imageUrl == null ? null : imageUrl.trim();
+ }
+
+ public String getCreateTime() {
+ return createTime;
+ }
+
+ public void setCreateTime(String createTime) {
+ this.createTime = createTime == null ? null : createTime.trim();
+ }
+
+ public Date getDownloadTime() {
+ return downloadTime;
+ }
+
+ public void setDownloadTime(Date downloadTime) {
+ this.downloadTime = downloadTime;
+ }
+
+ /**
+ * @Description equals
+ * @param that
+ * @return boolean
+ */
+ @Override
+ public boolean equals(Object that) {
+ if (this == that) {
+ return true;
+ }
+ if (that == null) {
+ return false;
+ }
+ if (getClass() != that.getClass()) {
+ return false;
+ }
+ RecordingDownloadDO other = (RecordingDownloadDO) that;
+ return (this.getApplicationNumber() == null ? other.getApplicationNumber() == null : this.getApplicationNumber().equals(other.getApplicationNumber()))
+ && (this.getCallId() == null ? other.getCallId() == null : this.getCallId().equals(other.getCallId()))
+ && (this.getImageId() == null ? other.getImageId() == null : this.getImageId().equals(other.getImageId()))
+ && (this.getImageName() == null ? other.getImageName() == null : this.getImageName().equals(other.getImageName()))
+ && (this.getImageType() == null ? other.getImageType() == null : this.getImageType().equals(other.getImageType()))
+ && (this.getImageSize() == null ? other.getImageSize() == null : this.getImageSize().equals(other.getImageSize()))
+ && (this.getImageUrl() == null ? other.getImageUrl() == null : this.getImageUrl().equals(other.getImageUrl()))
+ && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
+ && (this.getDownloadTime() == null ? other.getDownloadTime() == null : this.getDownloadTime().equals(other.getDownloadTime()));
+ }
+
+ /**
+ * @Description hashCode
+ * @return int
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((getApplicationNumber() == null) ? 0 : getApplicationNumber().hashCode());
+ result = prime * result + ((getCallId() == null) ? 0 : getCallId().hashCode());
+ result = prime * result + ((getImageId() == null) ? 0 : getImageId().hashCode());
+ result = prime * result + ((getImageName() == null) ? 0 : getImageName().hashCode());
+ result = prime * result + ((getImageType() == null) ? 0 : getImageType().hashCode());
+ result = prime * result + ((getImageSize() == null) ? 0 : getImageSize().hashCode());
+ result = prime * result + ((getImageUrl() == null) ? 0 : getImageUrl().hashCode());
+ result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
+ result = prime * result + ((getDownloadTime() == null) ? 0 : getDownloadTime().hashCode());
+ return result;
+ }
+
+ /**
+ * @Description toString
+ * @return java.lang.String
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(getClass().getSimpleName());
+ sb.append(" [");
+ sb.append("Hash = ").append(hashCode());
+ sb.append(", applicationNumber=").append(applicationNumber);
+ sb.append(", callId=").append(callId);
+ sb.append(", imageId=").append(imageId);
+ sb.append(", imageName=").append(imageName);
+ sb.append(", imageType=").append(imageType);
+ sb.append(", imageSize=").append(imageSize);
+ sb.append(", imageUrl=").append(imageUrl);
+ sb.append(", createTime=").append(createTime);
+ sb.append(", downloadTime=").append(downloadTime);
+ sb.append(", serialVersionUID=").append(serialVersionUID);
+ sb.append("]");
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/gbg/activate/video/entity/RecordingPendingDownloadQueueDO.java b/src/main/java/com/gbg/activate/video/entity/RecordingPendingDownloadQueueDO.java
new file mode 100644
index 0000000..eb12b5e
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/entity/RecordingPendingDownloadQueueDO.java
@@ -0,0 +1,235 @@
+package com.gbg.activate.video.entity;
+
+import java.io.Serializable;
+import java.util.Date;
+
+public class RecordingPendingDownloadQueueDO implements Serializable {
+ /**
+ * @Fields Serial_Number 序号
+ */
+ private Long serialNumber;
+
+ /**
+ * @Fields Application_Number 申请编号
+ */
+ private String applicationNumber;
+
+ /**
+ * @Fields Call_Id 呼叫编号
+ */
+ private String callId;
+
+ /**
+ * @Fields Image_Id 唯一编号
+ */
+ private String imageId;
+
+ /**
+ * @Fields Download_Status 下载状态
+ */
+ private String downloadStatus;
+
+ /**
+ * @Fields Entry_Time 进入队列时间
+ */
+ private Date entryTime;
+
+ /**
+ * @Fields Invoke_Time 调用时间
+ */
+ private Date invokeTime;
+
+ /**
+ * @Fields Retry_Count
+ */
+ private Integer retryCount;
+
+ /**
+ * @Fields Max_Retry
+ */
+ private Integer maxRetry;
+
+ /**
+ * @Fields Invoke_Priority 调用优化级
+ */
+ private Integer invokePriority;
+
+ /**
+ * @Fields Error_Message 错误信息
+ */
+ private String errorMessage;
+
+ /**
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database table Video_Signing_Pending_Download_Queue
+ *
+ * @mbg.generated
+ */
+ private static final long serialVersionUID = 1L;
+
+ public Long getSerialNumber() {
+ return serialNumber;
+ }
+
+ public void setSerialNumber(Long serialNumber) {
+ this.serialNumber = serialNumber;
+ }
+
+ public String getApplicationNumber() {
+ return applicationNumber;
+ }
+
+ public void setApplicationNumber(String applicationNumber) {
+ this.applicationNumber = applicationNumber == null ? null : applicationNumber.trim();
+ }
+
+ public String getImageId() {
+ return imageId;
+ }
+
+ public void setImageId(String imageId) {
+ this.imageId = imageId;
+ }
+
+ public String getDownloadStatus() {
+ return downloadStatus;
+ }
+
+ public void setDownloadStatus(String downloadStatus) {
+ this.downloadStatus = downloadStatus == null ? null : downloadStatus.trim();
+ }
+
+ public Date getEntryTime() {
+ return entryTime;
+ }
+
+ public void setEntryTime(Date entryTime) {
+ this.entryTime = entryTime;
+ }
+
+ public Date getInvokeTime() {
+ return invokeTime;
+ }
+
+ public void setInvokeTime(Date invokeTime) {
+ this.invokeTime = invokeTime;
+ }
+
+ public Integer getRetryCount() {
+ return retryCount;
+ }
+
+ public void setRetryCount(Integer retryCount) {
+ this.retryCount = retryCount;
+ }
+
+ public Integer getMaxRetry() {
+ return maxRetry;
+ }
+
+ public void setMaxRetry(Integer maxRetry) {
+ this.maxRetry = maxRetry;
+ }
+
+ public Integer getInvokePriority() {
+ return invokePriority;
+ }
+
+ public void setInvokePriority(Integer invokePriority) {
+ this.invokePriority = invokePriority;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage == null ? null : errorMessage.trim();
+ }
+
+ public String getCallId() {
+ return callId;
+ }
+
+ public void setCallId(String callId) {
+ this.callId = callId;
+ }
+
+ /**
+ * @Description equals
+ * @param that
+ * @return boolean
+ */
+ @Override
+ public boolean equals(Object that) {
+ if (this == that) {
+ return true;
+ }
+ if (that == null) {
+ return false;
+ }
+ if (getClass() != that.getClass()) {
+ return false;
+ }
+ RecordingPendingDownloadQueueDO other = (RecordingPendingDownloadQueueDO) that;
+ return (this.getSerialNumber() == null ? other.getSerialNumber() == null : this.getSerialNumber().equals(other.getSerialNumber()))
+ && (this.getApplicationNumber() == null ? other.getApplicationNumber() == null : this.getApplicationNumber().equals(other.getApplicationNumber()))
+ && (this.getCallId() == null ? other.getCallId() == null : this.getCallId().equals(other.getCallId()))
+ && (this.getImageId() == null ? other.getImageId() == null : this.getImageId().equals(other.getImageId()))
+ && (this.getDownloadStatus() == null ? other.getDownloadStatus() == null : this.getDownloadStatus().equals(other.getDownloadStatus()))
+ && (this.getEntryTime() == null ? other.getEntryTime() == null : this.getEntryTime().equals(other.getEntryTime()))
+ && (this.getInvokeTime() == null ? other.getInvokeTime() == null : this.getInvokeTime().equals(other.getInvokeTime()))
+ && (this.getRetryCount() == null ? other.getRetryCount() == null : this.getRetryCount().equals(other.getRetryCount()))
+ && (this.getMaxRetry() == null ? other.getMaxRetry() == null : this.getMaxRetry().equals(other.getMaxRetry()))
+ && (this.getInvokePriority() == null ? other.getInvokePriority() == null : this.getInvokePriority().equals(other.getInvokePriority()))
+ && (this.getErrorMessage() == null ? other.getErrorMessage() == null : this.getErrorMessage().equals(other.getErrorMessage()));
+ }
+
+ /**
+ * @Description hashCode
+ * @return int
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((getSerialNumber() == null) ? 0 : getSerialNumber().hashCode());
+ result = prime * result + ((getApplicationNumber() == null) ? 0 : getApplicationNumber().hashCode());
+ result = prime * result + ((getCallId() == null) ? 0 : getCallId().hashCode());
+ result = prime * result + ((getImageId() == null) ? 0 : getImageId().hashCode());
+ result = prime * result + ((getDownloadStatus() == null) ? 0 : getDownloadStatus().hashCode());
+ result = prime * result + ((getEntryTime() == null) ? 0 : getEntryTime().hashCode());
+ result = prime * result + ((getInvokeTime() == null) ? 0 : getInvokeTime().hashCode());
+ result = prime * result + ((getRetryCount() == null) ? 0 : getRetryCount().hashCode());
+ result = prime * result + ((getMaxRetry() == null) ? 0 : getMaxRetry().hashCode());
+ result = prime * result + ((getInvokePriority() == null) ? 0 : getInvokePriority().hashCode());
+ result = prime * result + ((getErrorMessage() == null) ? 0 : getErrorMessage().hashCode());
+ return result;
+ }
+
+ /**
+ * @Description toString
+ * @return java.lang.String
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(getClass().getSimpleName());
+ sb.append(" [");
+ sb.append("Hash = ").append(hashCode());
+ sb.append(", serialNumber=").append(serialNumber);
+ sb.append(", applicationNumber=").append(applicationNumber);
+ sb.append(", callId=").append(callId);
+ sb.append(", imageId=").append(imageId);
+ sb.append(", downloadStatus=").append(downloadStatus);
+ sb.append(", entryTime=").append(entryTime);
+ sb.append(", invokeTime=").append(invokeTime);
+ sb.append(", retryCount=").append(retryCount);
+ sb.append(", maxRetry=").append(maxRetry);
+ sb.append(", invokePriority=").append(invokePriority);
+ sb.append(", errorMessage=").append(errorMessage);
+ sb.append(", serialVersionUID=").append(serialVersionUID);
+ sb.append("]");
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/gbg/activate/video/entity/VideoSigningDownloadRecordDO.java b/src/main/java/com/gbg/activate/video/entity/VideoSigningDownloadRecordDO.java
new file mode 100644
index 0000000..c44b359
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/entity/VideoSigningDownloadRecordDO.java
@@ -0,0 +1,203 @@
+package com.gbg.activate.video.entity;
+
+import java.io.Serializable;
+import java.util.Date;
+
+public class VideoSigningDownloadRecordDO implements Serializable {
+ /**
+ * @Fields Application_Number 申请编号
+ */
+ private String applicationNumber;
+
+ /**
+ * @Fields Image_Id 唯一编号
+ */
+ private String imageId;
+
+ /**
+ * @Fields Image_Name 文件名称
+ */
+ private String imageName;
+
+ /**
+ * @Fields Image_Type 文件类型
+ */
+ private String imageType;
+
+ /**
+ * @Fields Image_Size 文件大小
+ */
+ private String imageSize;
+
+ /**
+ * @Fields Image_Url 文件下载链接
+ */
+ private String imageUrl;
+
+ /**
+ * @Fields Video_Duration 视频长度
+ */
+ private String videoDuration;
+
+ /**
+ * @Fields Create_Time 创建时间
+ */
+ private String createTime;
+
+ /**
+ * @Fields Download_Time 下载时间
+ */
+ private Date downloadTime;
+
+ /**
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database table Video_Signing_Download_Record
+ *
+ * @mbg.generated
+ */
+ private static final long serialVersionUID = 1L;
+
+ public String getApplicationNumber() {
+ return applicationNumber;
+ }
+
+ public void setApplicationNumber(String applicationNumber) {
+ this.applicationNumber = applicationNumber == null ? null : applicationNumber.trim();
+ }
+
+ public String getImageId() {
+ return imageId;
+ }
+
+ public void setImageId(String imageId) {
+ this.imageId = imageId == null ? null : imageId.trim();
+ }
+
+ public String getImageName() {
+ return imageName;
+ }
+
+ public void setImageName(String imageName) {
+ this.imageName = imageName == null ? null : imageName.trim();
+ }
+
+ public String getImageType() {
+ return imageType;
+ }
+
+ public void setImageType(String imageType) {
+ this.imageType = imageType == null ? null : imageType.trim();
+ }
+
+ public String getImageSize() {
+ return imageSize;
+ }
+
+ public void setImageSize(String imageSize) {
+ this.imageSize = imageSize == null ? null : imageSize.trim();
+ }
+
+ public String getImageUrl() {
+ return imageUrl;
+ }
+
+ public void setImageUrl(String imageUrl) {
+ this.imageUrl = imageUrl == null ? null : imageUrl.trim();
+ }
+
+ public String getVideoDuration() {
+ return videoDuration;
+ }
+
+ public void setVideoDuration(String videoDuration) {
+ this.videoDuration = videoDuration == null ? null : videoDuration.trim();
+ }
+
+ public String getCreateTime() {
+ return createTime;
+ }
+
+ public void setCreateTime(String createTime) {
+ this.createTime = createTime == null ? null : createTime.trim();
+ }
+
+ public Date getDownloadTime() {
+ return downloadTime;
+ }
+
+ public void setDownloadTime(Date downloadTime) {
+ this.downloadTime = downloadTime;
+ }
+
+ /**
+ * @Description equals
+ * @param that
+ * @return boolean
+ */
+ @Override
+ public boolean equals(Object that) {
+ if (this == that) {
+ return true;
+ }
+ if (that == null) {
+ return false;
+ }
+ if (getClass() != that.getClass()) {
+ return false;
+ }
+ VideoSigningDownloadRecordDO other = (VideoSigningDownloadRecordDO) that;
+ return (this.getApplicationNumber() == null ? other.getApplicationNumber() == null : this.getApplicationNumber().equals(other.getApplicationNumber()))
+ && (this.getImageId() == null ? other.getImageId() == null : this.getImageId().equals(other.getImageId()))
+ && (this.getImageName() == null ? other.getImageName() == null : this.getImageName().equals(other.getImageName()))
+ && (this.getImageType() == null ? other.getImageType() == null : this.getImageType().equals(other.getImageType()))
+ && (this.getImageSize() == null ? other.getImageSize() == null : this.getImageSize().equals(other.getImageSize()))
+ && (this.getImageUrl() == null ? other.getImageUrl() == null : this.getImageUrl().equals(other.getImageUrl()))
+ && (this.getVideoDuration() == null ? other.getVideoDuration() == null : this.getVideoDuration().equals(other.getVideoDuration()))
+ && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
+ && (this.getDownloadTime() == null ? other.getDownloadTime() == null : this.getDownloadTime().equals(other.getDownloadTime()));
+ }
+
+ /**
+ * @Description hashCode
+ * @return int
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((getApplicationNumber() == null) ? 0 : getApplicationNumber().hashCode());
+ result = prime * result + ((getImageId() == null) ? 0 : getImageId().hashCode());
+ result = prime * result + ((getImageName() == null) ? 0 : getImageName().hashCode());
+ result = prime * result + ((getImageType() == null) ? 0 : getImageType().hashCode());
+ result = prime * result + ((getImageSize() == null) ? 0 : getImageSize().hashCode());
+ result = prime * result + ((getImageUrl() == null) ? 0 : getImageUrl().hashCode());
+ result = prime * result + ((getVideoDuration() == null) ? 0 : getVideoDuration().hashCode());
+ result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
+ result = prime * result + ((getDownloadTime() == null) ? 0 : getDownloadTime().hashCode());
+ return result;
+ }
+
+ /**
+ * @Description toString
+ * @return java.lang.String
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(getClass().getSimpleName());
+ sb.append(" [");
+ sb.append("Hash = ").append(hashCode());
+ sb.append(", applicationNumber=").append(applicationNumber);
+ sb.append(", imageId=").append(imageId);
+ sb.append(", imageName=").append(imageName);
+ sb.append(", imageType=").append(imageType);
+ sb.append(", imageSize=").append(imageSize);
+ sb.append(", imageUrl=").append(imageUrl);
+ sb.append(", videoDuration=").append(videoDuration);
+ sb.append(", createTime=").append(createTime);
+ sb.append(", downloadTime=").append(downloadTime);
+ sb.append(", serialVersionUID=").append(serialVersionUID);
+ sb.append("]");
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/gbg/activate/video/entity/VideoSigningPendingDownloadQueueDO.java b/src/main/java/com/gbg/activate/video/entity/VideoSigningPendingDownloadQueueDO.java
new file mode 100644
index 0000000..fe9c396
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/entity/VideoSigningPendingDownloadQueueDO.java
@@ -0,0 +1,235 @@
+package com.gbg.activate.video.entity;
+
+import java.io.Serializable;
+import java.util.Date;
+
+public class VideoSigningPendingDownloadQueueDO implements Serializable {
+ /**
+ * @Fields Serial_Number 序号
+ */
+ private Long serialNumber;
+
+ /**
+ * @Fields Application_Number 申请编号
+ */
+ private String applicationNumber;
+
+ /**
+ * @Fields Trade_Number 交易流水号
+ */
+ private String tradeNumber;
+
+ /**
+ * @Fields Customer_Number 客户号
+ */
+ private String customerNumber;
+
+ /**
+ * @Fields Download_Status 下载状态
+ */
+ private String downloadStatus;
+
+ /**
+ * @Fields Entry_Time 进入队列时间
+ */
+ private Date entryTime;
+
+ /**
+ * @Fields Invoke_Time 调用时间
+ */
+ private Date invokeTime;
+
+ /**
+ * @Fields Retry_Count
+ */
+ private Integer retryCount;
+
+ /**
+ * @Fields Max_Retry
+ */
+ private Integer maxRetry;
+
+ /**
+ * @Fields Invoke_Priority 调用优化级
+ */
+ private Integer invokePriority;
+
+ /**
+ * @Fields Error_Message 错误信息
+ */
+ private String errorMessage;
+
+ /**
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database table Video_Signing_Pending_Download_Queue
+ *
+ * @mbg.generated
+ */
+ private static final long serialVersionUID = 1L;
+
+ public Long getSerialNumber() {
+ return serialNumber;
+ }
+
+ public void setSerialNumber(Long serialNumber) {
+ this.serialNumber = serialNumber;
+ }
+
+ public String getApplicationNumber() {
+ return applicationNumber;
+ }
+
+ public void setApplicationNumber(String applicationNumber) {
+ this.applicationNumber = applicationNumber == null ? null : applicationNumber.trim();
+ }
+
+ public String getTradeNumber() {
+ return tradeNumber;
+ }
+
+ public void setTradeNumber(String tradeNumber) {
+ this.tradeNumber = tradeNumber == null ? null : tradeNumber.trim();
+ }
+
+ public String getCustomerNumber() {
+ return customerNumber;
+ }
+
+ public void setCustomerNumber(String customerNumber) {
+ this.customerNumber = customerNumber == null ? null : customerNumber.trim();
+ }
+
+ public String getDownloadStatus() {
+ return downloadStatus;
+ }
+
+ public void setDownloadStatus(String downloadStatus) {
+ this.downloadStatus = downloadStatus == null ? null : downloadStatus.trim();
+ }
+
+ public Date getEntryTime() {
+ return entryTime;
+ }
+
+ public void setEntryTime(Date entryTime) {
+ this.entryTime = entryTime;
+ }
+
+ public Date getInvokeTime() {
+ return invokeTime;
+ }
+
+ public void setInvokeTime(Date invokeTime) {
+ this.invokeTime = invokeTime;
+ }
+
+ public Integer getRetryCount() {
+ return retryCount;
+ }
+
+ public void setRetryCount(Integer retryCount) {
+ this.retryCount = retryCount;
+ }
+
+ public Integer getMaxRetry() {
+ return maxRetry;
+ }
+
+ public void setMaxRetry(Integer maxRetry) {
+ this.maxRetry = maxRetry;
+ }
+
+ public Integer getInvokePriority() {
+ return invokePriority;
+ }
+
+ public void setInvokePriority(Integer invokePriority) {
+ this.invokePriority = invokePriority;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage == null ? null : errorMessage.trim();
+ }
+
+ /**
+ * @Description equals
+ * @param that
+ * @return boolean
+ */
+ @Override
+ public boolean equals(Object that) {
+ if (this == that) {
+ return true;
+ }
+ if (that == null) {
+ return false;
+ }
+ if (getClass() != that.getClass()) {
+ return false;
+ }
+ VideoSigningPendingDownloadQueueDO other = (VideoSigningPendingDownloadQueueDO) that;
+ return (this.getSerialNumber() == null ? other.getSerialNumber() == null : this.getSerialNumber().equals(other.getSerialNumber()))
+ && (this.getApplicationNumber() == null ? other.getApplicationNumber() == null : this.getApplicationNumber().equals(other.getApplicationNumber()))
+ && (this.getTradeNumber() == null ? other.getTradeNumber() == null : this.getTradeNumber().equals(other.getTradeNumber()))
+ && (this.getCustomerNumber() == null ? other.getCustomerNumber() == null : this.getCustomerNumber().equals(other.getCustomerNumber()))
+ && (this.getDownloadStatus() == null ? other.getDownloadStatus() == null : this.getDownloadStatus().equals(other.getDownloadStatus()))
+ && (this.getEntryTime() == null ? other.getEntryTime() == null : this.getEntryTime().equals(other.getEntryTime()))
+ && (this.getInvokeTime() == null ? other.getInvokeTime() == null : this.getInvokeTime().equals(other.getInvokeTime()))
+ && (this.getRetryCount() == null ? other.getRetryCount() == null : this.getRetryCount().equals(other.getRetryCount()))
+ && (this.getMaxRetry() == null ? other.getMaxRetry() == null : this.getMaxRetry().equals(other.getMaxRetry()))
+ && (this.getInvokePriority() == null ? other.getInvokePriority() == null : this.getInvokePriority().equals(other.getInvokePriority()))
+ && (this.getErrorMessage() == null ? other.getErrorMessage() == null : this.getErrorMessage().equals(other.getErrorMessage()));
+ }
+
+ /**
+ * @Description hashCode
+ * @return int
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((getSerialNumber() == null) ? 0 : getSerialNumber().hashCode());
+ result = prime * result + ((getApplicationNumber() == null) ? 0 : getApplicationNumber().hashCode());
+ result = prime * result + ((getTradeNumber() == null) ? 0 : getTradeNumber().hashCode());
+ result = prime * result + ((getCustomerNumber() == null) ? 0 : getCustomerNumber().hashCode());
+ result = prime * result + ((getDownloadStatus() == null) ? 0 : getDownloadStatus().hashCode());
+ result = prime * result + ((getEntryTime() == null) ? 0 : getEntryTime().hashCode());
+ result = prime * result + ((getInvokeTime() == null) ? 0 : getInvokeTime().hashCode());
+ result = prime * result + ((getRetryCount() == null) ? 0 : getRetryCount().hashCode());
+ result = prime * result + ((getMaxRetry() == null) ? 0 : getMaxRetry().hashCode());
+ result = prime * result + ((getInvokePriority() == null) ? 0 : getInvokePriority().hashCode());
+ result = prime * result + ((getErrorMessage() == null) ? 0 : getErrorMessage().hashCode());
+ return result;
+ }
+
+ /**
+ * @Description toString
+ * @return java.lang.String
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(getClass().getSimpleName());
+ sb.append(" [");
+ sb.append("Hash = ").append(hashCode());
+ sb.append(", serialNumber=").append(serialNumber);
+ sb.append(", applicationNumber=").append(applicationNumber);
+ sb.append(", tradeNumber=").append(tradeNumber);
+ sb.append(", customerNumber=").append(customerNumber);
+ sb.append(", downloadStatus=").append(downloadStatus);
+ sb.append(", entryTime=").append(entryTime);
+ sb.append(", invokeTime=").append(invokeTime);
+ sb.append(", retryCount=").append(retryCount);
+ sb.append(", maxRetry=").append(maxRetry);
+ sb.append(", invokePriority=").append(invokePriority);
+ sb.append(", errorMessage=").append(errorMessage);
+ sb.append(", serialVersionUID=").append(serialVersionUID);
+ sb.append("]");
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/gbg/activate/video/job/AudioFileCleanupJob.java b/src/main/java/com/gbg/activate/video/job/AudioFileCleanupJob.java
new file mode 100644
index 0000000..e136635
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/job/AudioFileCleanupJob.java
@@ -0,0 +1,27 @@
+package com.gbg.activate.video.job;
+
+import com.gbg.activate.video.service.IAudioFileCleanupService;
+import com.gbg.activate.video.service.IDownloadTaskService;
+import org.quartz.DisallowConcurrentExecution;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.quartz.QuartzJobBean;
+
+@DisallowConcurrentExecution
+public class AudioFileCleanupJob extends QuartzJobBean {
+ private static final Logger LOG = LoggerFactory.getLogger(AudioFileCleanupJob.class);
+
+ @Autowired
+ private IAudioFileCleanupService cleanupService;
+
+ @Override
+ protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
+ LOG.info("Execute Download Job: {}", context.getJobDetail().getKey().getName());
+ int files = cleanupService.cleanupOldAudioFiles();
+ LOG.info("录音文件清理任务完成,共删除 {} 个文件", files);
+ }///
+
+}
diff --git a/src/main/java/com/gbg/activate/video/job/ClearExpiredFileJob.java b/src/main/java/com/gbg/activate/video/job/ClearExpiredFileJob.java
new file mode 100644
index 0000000..fd2b84e
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/job/ClearExpiredFileJob.java
@@ -0,0 +1,26 @@
+package com.gbg.activate.video.job;
+
+import org.quartz.DisallowConcurrentExecution;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.quartz.QuartzJobBean;
+
+import com.gbg.activate.video.service.IClearExpiredFileService;
+
+@DisallowConcurrentExecution
+public class ClearExpiredFileJob extends QuartzJobBean {
+ private static final Logger LOG = LoggerFactory.getLogger(ClearExpiredFileJob.class);
+
+ @Autowired
+ private IClearExpiredFileService clearService;
+
+ @Override
+ protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
+ LOG.info("Execute Clear Expired File Job: {}", context.getJobDetail().getKey().getName());
+ clearService.clearExpiredFiles();
+ }
+
+}
diff --git a/src/main/java/com/gbg/activate/video/job/RecordingDownloadJob.java b/src/main/java/com/gbg/activate/video/job/RecordingDownloadJob.java
new file mode 100644
index 0000000..189362b
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/job/RecordingDownloadJob.java
@@ -0,0 +1,26 @@
+package com.gbg.activate.video.job;
+
+import com.gbg.activate.video.service.IDownloadRecordingTaskService;
+import com.gbg.activate.video.service.IDownloadTaskService;
+import org.quartz.DisallowConcurrentExecution;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.quartz.QuartzJobBean;
+
+@DisallowConcurrentExecution
+public class RecordingDownloadJob extends QuartzJobBean {
+ private static final Logger LOG = LoggerFactory.getLogger(RecordingDownloadJob.class);
+
+ @Autowired
+ private IDownloadRecordingTaskService downloadRecordingTaskService;
+
+ @Override
+ protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
+ LOG.info("Execute Download Job: {}", context.getJobDetail().getKey().getName());
+ downloadRecordingTaskService.processPendingTasks();
+ }
+
+}
diff --git a/src/main/java/com/gbg/activate/video/job/VideoDownloadJob.java b/src/main/java/com/gbg/activate/video/job/VideoDownloadJob.java
new file mode 100644
index 0000000..ac05b58
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/job/VideoDownloadJob.java
@@ -0,0 +1,26 @@
+package com.gbg.activate.video.job;
+
+import org.quartz.DisallowConcurrentExecution;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.quartz.QuartzJobBean;
+
+import com.gbg.activate.video.service.IDownloadTaskService;
+
+@DisallowConcurrentExecution
+public class VideoDownloadJob extends QuartzJobBean {
+ private static final Logger LOG = LoggerFactory.getLogger(VideoDownloadJob.class);
+
+ @Autowired
+ private IDownloadTaskService downloadService;
+
+ @Override
+ protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
+ LOG.info("Execute Download Job: {}", context.getJobDetail().getKey().getName());
+ downloadService.processPendingTasks();
+ }
+
+}
diff --git a/src/main/java/com/gbg/activate/video/mapper/RecordingDownloadMapper.java b/src/main/java/com/gbg/activate/video/mapper/RecordingDownloadMapper.java
new file mode 100644
index 0000000..a768910
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/mapper/RecordingDownloadMapper.java
@@ -0,0 +1,110 @@
+package com.gbg.activate.video.mapper;
+
+import com.gbg.activate.video.entity.RecordingDownloadDO;
+import com.gbg.activate.video.entity.VideoSigningDownloadRecordDO;
+import org.apache.ibatis.annotations.*;
+import org.apache.ibatis.type.JdbcType;
+
+@Mapper
+public interface RecordingDownloadMapper {
+ /**
+ * @Description 根据主键删除表中记录
+ * @param applicationNumber
+ * @param imageId
+ * @return int
+ */
+ @Delete({
+ "delete from Recording_DownLoad_Record",
+ "where Application_Number = #{applicationNumber,jdbcType=NVARCHAR}",
+ "and Image_Id = #{imageId,jdbcType=NVARCHAR}"
+ })
+ int deleteByPrimaryKey(@Param("applicationNumber") String applicationNumber, @Param("imageId") String imageId);
+
+ /**
+ * @Description 向表中插入新记录
+ * @param record
+ * @return int
+ */
+ @Insert({
+ "insert into Recording_DownLoad_Record (Application_Number, Call_Id, ",
+ "Image_Id,Image_Name, Image_Type, ",
+ "Image_Size, ",
+ "Create_Time, Download_Time,Image_Url)",
+ "values (#{applicationNumber,jdbcType=NVARCHAR}, #{callId,jdbcType=NVARCHAR}, ",
+ "#{imageId,jdbcType=NVARCHAR}, #{imageName,jdbcType=NVARCHAR}, #{imageType,jdbcType=NVARCHAR}, ",
+ "#{imageSize,jdbcType=NVARCHAR}, ",
+ "#{createTime,jdbcType=NVARCHAR}, #{downloadTime,jdbcType=TIMESTAMP}, #{imageUrl,jdbcType=NVARCHAR})"
+ })
+ int insert(RecordingDownloadDO record);
+
+ /**
+ * @Description 选择对象中的非空字段向表中插入新记录
+ * @param record
+ * @return int
+ */
+ @InsertProvider(type=RecordingDownloadSqlProvider.class, method="insertSelective")
+ int insertSelective(RecordingDownloadDO record);
+
+ /**
+ * @Description 根据主键查询表中记录
+ * @param applicationNumber
+ * @param imageId
+ * @return com.gbg.activate.entity.dao.VideoSigningDownloadRecordDO
+ */
+ @Select({
+ "select",
+ "Application_Number, Call_Id, Image_Id, Image_Name, Image_Type, Image_Size, ",
+ "Create_Time, Download_Time",
+ "from Recording_DownLoad_Record",
+ "where Application_Number = #{applicationNumber,jdbcType=NVARCHAR}",
+ "and Image_Id = #{imageId,jdbcType=NVARCHAR}"
+ })
+ @Results({
+ @Result(column="Application_Number", property="applicationNumber", jdbcType=JdbcType.NVARCHAR, id=true),
+ @Result(column="Call_Id", property="callId", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Image_Id", property="imageId", jdbcType=JdbcType.NVARCHAR, id=true),
+ @Result(column="Image_Name", property="imageName", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Image_Type", property="imageType", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Image_Size", property="imageSize", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Create_Time", property="createTime", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Download_Time", property="downloadTime", jdbcType=JdbcType.TIMESTAMP)
+ })
+ RecordingDownloadDO selectByPrimaryKey(@Param("applicationNumber") String applicationNumber, @Param("imageId") String imageId);
+
+ /**
+ * @Description 根据主键选择对象中的非空字段更新表中记录
+ * @param record
+ * @return int
+ */
+ @UpdateProvider(type=RecordingDownloadSqlProvider.class, method="updateByPrimaryKeySelective")
+ int updateByPrimaryKeySelective(RecordingDownloadDO record);
+
+ /**
+ * @Description 根据主键更新表中记录
+ * @param record
+ * @return int
+ */
+ @Update({
+ "update Recording_DownLoad_Record",
+ "set Call_Id = #{callId,jdbcType=NVARCHAR},",
+ "Image_Name = #{imageName,jdbcType=NVARCHAR},",
+ "Image_Type = #{imageType,jdbcType=NVARCHAR},",
+ "Image_Size = #{imageSize,jdbcType=NVARCHAR},",
+ "Create_Time = #{createTime,jdbcType=NVARCHAR},",
+ "Download_Time = #{downloadTime,jdbcType=TIMESTAMP}",
+ "where Application_Number = #{applicationNumber,jdbcType=NVARCHAR}",
+ "and Image_Id = #{imageId,jdbcType=NVARCHAR}"
+ })
+ int updateByPrimaryKey(RecordingDownloadDO record);
+
+ /**
+ * 根据申请编号删除记录
+ * @param applicationNumber
+ * @return
+ */
+ @Delete({
+ "delete from Recording_DownLoad_Record",
+ "where Application_Number = #{applicationNumber,jdbcType=NVARCHAR}"
+ })
+ int deleteByApplicationNumber(@Param("applicationNumber") String applicationNumber);
+}
\ No newline at end of file
diff --git a/src/main/java/com/gbg/activate/video/mapper/RecordingDownloadSqlProvider.java b/src/main/java/com/gbg/activate/video/mapper/RecordingDownloadSqlProvider.java
new file mode 100644
index 0000000..d8ac8df
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/mapper/RecordingDownloadSqlProvider.java
@@ -0,0 +1,101 @@
+package com.gbg.activate.video.mapper;
+
+import com.gbg.activate.video.entity.RecordingDownloadDO;
+import com.gbg.activate.video.entity.VideoSigningDownloadRecordDO;
+import org.apache.ibatis.jdbc.SQL;
+
+public class RecordingDownloadSqlProvider {
+
+ /**
+ * @Description 选择对象中的非空字段向表中插入新记录
+ * @param record
+ * @return java.lang.String
+ */
+ public String insertSelective(RecordingDownloadDO record) {
+ SQL sql = new SQL();
+ sql.INSERT_INTO("Recording_DownLoad_Record");
+
+ if (record.getApplicationNumber() != null) {
+ sql.VALUES("Application_Number", "#{applicationNumber,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getCallId() != null) {
+ sql.VALUES("Call_Id", "#{callId,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getImageId() != null) {
+ sql.VALUES("Image_Id", "#{imageId,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getImageName() != null) {
+ sql.VALUES("Image_Name", "#{imageName,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getImageType() != null) {
+ sql.VALUES("Image_Type", "#{imageType,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getImageSize() != null) {
+ sql.VALUES("Image_Size", "#{imageSize,jdbcType=NVARCHAR}");
+ }
+
+
+ if (record.getCreateTime() != null) {
+ sql.VALUES("Create_Time", "#{createTime,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getDownloadTime() != null) {
+ sql.VALUES("Download_Time", "#{downloadTime,jdbcType=TIMESTAMP}");
+ }
+
+ if (record.getImageUrl() != null) {
+ sql.VALUES("Image_Url", "#{imageUrl,jdbcType=TIMESTAMP}");
+ }
+
+ return sql.toString();
+ }
+
+ /**
+ * @Description 根据主键选择对象中的非空字段更新表中记录
+ * @param record
+ * @return java.lang.String
+ */
+ public String updateByPrimaryKeySelective(RecordingDownloadDO record) {
+ SQL sql = new SQL();
+ sql.UPDATE("Recording_DownLoad_Record");
+
+ if (record.getCallId() != null) {
+ sql.SET("Call_Id = #{callId,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getImageName() != null) {
+ sql.SET("Image_Name = #{imageName,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getImageType() != null) {
+ sql.SET("Image_Type = #{imageType,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getImageSize() != null) {
+ sql.SET("Image_Size = #{imageSize,jdbcType=NVARCHAR}");
+ }
+
+
+ if (record.getCreateTime() != null) {
+ sql.SET("Create_Time = #{createTime,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getDownloadTime() != null) {
+ sql.SET("Download_Time = #{downloadTime,jdbcType=TIMESTAMP}");
+ }
+
+ if (record.getImageUrl() != null) {
+ sql.VALUES("Image_Url", "#{imageUrl,jdbcType=TIMESTAMP}");
+ }
+
+ sql.WHERE("Application_Number = #{applicationNumber,jdbcType=NVARCHAR}");
+ sql.WHERE("Image_Id = #{imageId,jdbcType=NVARCHAR}");
+
+ return sql.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/gbg/activate/video/mapper/RecordingPendingDownloadQueueMapper.java b/src/main/java/com/gbg/activate/video/mapper/RecordingPendingDownloadQueueMapper.java
new file mode 100644
index 0000000..c4d07c5
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/mapper/RecordingPendingDownloadQueueMapper.java
@@ -0,0 +1,128 @@
+package com.gbg.activate.video.mapper;
+
+import com.gbg.activate.video.entity.RecordingPendingDownloadQueueDO;
+import com.gbg.activate.video.entity.VideoSigningPendingDownloadQueueDO;
+import org.apache.ibatis.annotations.*;
+import org.apache.ibatis.type.JdbcType;
+
+import java.util.List;
+
+@Mapper
+public interface RecordingPendingDownloadQueueMapper {
+ /**
+ * @Description 根据主键删除表中记录
+ * @param serialNumber
+ * @return int
+ */
+ @Delete({
+ "delete from Recording_Pending_Download_Queue",
+ "where Serial_Number = #{serialNumber,jdbcType=BIGINT}"
+ })
+ int deleteByPrimaryKey(Long serialNumber);
+
+ /**
+ * @Description 向表中插入新记录
+ * @param record
+ * @return int
+ */
+ @Insert({
+ "insert into Recording_Pending_Download_Queue (Serial_Number, Application_Number, ",
+ "Call_Id,Image_Id, ",
+ "Download_Status, Entry_Time, ",
+ "Invoke_Time, Retry_Count, ",
+ "Max_Retry, Invoke_Priority, ",
+ "Error_Message)",
+ "values (#{serialNumber,jdbcType=BIGINT}, #{applicationNumber,jdbcType=NVARCHAR}, ",
+ "#{imageId,jdbcType=NVARCHAR}, ",
+ "#{downloadStatus,jdbcType=NVARCHAR}, #{entryTime,jdbcType=TIMESTAMP}, ",
+ "#{invokeTime,jdbcType=TIMESTAMP}, #{retryCount,jdbcType=INTEGER}, ",
+ "#{maxRetry,jdbcType=INTEGER}, #{invokePriority,jdbcType=INTEGER}, ",
+ "#{errorMessage,jdbcType=NVARCHAR})"
+ })
+ int insert(RecordingPendingDownloadQueueDO record);
+
+ /**
+ * @Description 选择对象中的非空字段向表中插入新记录
+ * @param record
+ * @return int
+ */
+ @InsertProvider(type=RecordingPendingDownloadQueueSqlProvider.class, method="insertSelective")
+ int insertSelective(RecordingPendingDownloadQueueDO record);
+
+ /**
+ * @Description 根据主键查询表中记录
+ * @param serialNumber
+ * @return com.gbg.activate.entity.dao.VideoSigningPendingDownloadQueueDO
+ */
+ @Select({
+ "select",
+ "Serial_Number, Application_Number, Call_Id,Image_Id, Download_Status, ",
+ "Entry_Time, Invoke_Time, Retry_Count, Max_Retry, Invoke_Priority, Error_Message",
+ "from Recording_Pending_Download_Queue",
+ "where Serial_Number = #{serialNumber,jdbcType=BIGINT}"
+ })
+ @Results(id="RecordingPendingDownloadQueueMap", value={
+ @Result(column="Serial_Number", property="serialNumber", jdbcType=JdbcType.BIGINT, id=true),
+ @Result(column="Application_Number", property="applicationNumber", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Call_Id", property="callId", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Image_Id", property="imageId", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Download_Status", property="downloadStatus", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Entry_Time", property="entryTime", jdbcType=JdbcType.TIMESTAMP),
+ @Result(column="Invoke_Time", property="invokeTime", jdbcType=JdbcType.TIMESTAMP),
+ @Result(column="Retry_Count", property="retryCount", jdbcType=JdbcType.INTEGER),
+ @Result(column="Max_Retry", property="maxRetry", jdbcType=JdbcType.INTEGER),
+ @Result(column="Invoke_Priority", property="invokePriority", jdbcType=JdbcType.INTEGER),
+ @Result(column="Error_Message", property="errorMessage", jdbcType=JdbcType.NVARCHAR)
+ })
+ RecordingPendingDownloadQueueDO selectByPrimaryKey(Long serialNumber);
+
+ /**
+ * @Description 根据主键选择对象中的非空字段更新表中记录
+ * @param record
+ * @return int
+ */
+ @UpdateProvider(type=RecordingPendingDownloadQueueSqlProvider.class, method="updateByPrimaryKeySelective")
+ int updateByPrimaryKeySelective(RecordingPendingDownloadQueueDO record);
+
+ /**
+ * @Description 根据主键更新表中记录
+ * @param record
+ * @return int
+ */
+ @Update({
+ "update Recording_Pending_Download_Queue",
+ "set Application_Number = #{applicationNumber,jdbcType=NVARCHAR},",
+ "Call_Id = #{callId,jdbcType=NVARCHAR},",
+ "Image_Id = #{imageId,jdbcType=NVARCHAR},",
+ "Download_Status = #{downloadStatus,jdbcType=NVARCHAR},",
+ "Entry_Time = #{entryTime,jdbcType=TIMESTAMP},",
+ "Invoke_Time = #{invokeTime,jdbcType=TIMESTAMP},",
+ "Retry_Count = #{retryCount,jdbcType=INTEGER},",
+ "Max_Retry = #{maxRetry,jdbcType=INTEGER},",
+ "Invoke_Priority = #{invokePriority,jdbcType=INTEGER},",
+ "Error_Message = #{errorMessage,jdbcType=NVARCHAR}",
+ "where Serial_Number = #{serialNumber,jdbcType=BIGINT}"
+ })
+ int updateByPrimaryKey(RecordingPendingDownloadQueueDO record);
+
+ /**
+ * @Title: fetchPendingTasks
+ * @Description: 获取待下载的任务列表
+ * @return 参数
+ * @return List 返回类型
+ * @throws
+ * @author Frank.Wang@gbgplc.com
+ * @date 2025-07-15 05:52:16
+ */
+ @Select({
+ "SELECT TOP (100)",
+ "Serial_Number, Application_Number, Call_Id, Image_Id, Download_Status, ",
+ "Entry_Time, Invoke_Time, Retry_Count, Max_Retry, Invoke_Priority, Error_Message",
+ "FROM Recording_Pending_Download_Queue WITH(NOLOCK)",
+ "WHERE Download_Status = 'PENDING'",
+ "ORDER BY Invoke_Priority DESC"
+ })
+ @ResultMap("RecordingPendingDownloadQueueMap")
+ List fetchPendingTasks();
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/gbg/activate/video/mapper/RecordingPendingDownloadQueueSqlProvider.java b/src/main/java/com/gbg/activate/video/mapper/RecordingPendingDownloadQueueSqlProvider.java
new file mode 100644
index 0000000..5e83ac6
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/mapper/RecordingPendingDownloadQueueSqlProvider.java
@@ -0,0 +1,120 @@
+package com.gbg.activate.video.mapper;
+
+import com.gbg.activate.video.entity.RecordingPendingDownloadQueueDO;
+import com.gbg.activate.video.entity.VideoSigningPendingDownloadQueueDO;
+import org.apache.ibatis.jdbc.SQL;
+
+public class RecordingPendingDownloadQueueSqlProvider {
+
+ /**
+ * @Description 选择对象中的非空字段向表中插入新记录
+ * @param record
+ * @return java.lang.String
+ */
+ public String insertSelective(RecordingPendingDownloadQueueDO record) {
+ SQL sql = new SQL();
+ sql.INSERT_INTO("Recording_Pending_Download_Queue");
+
+ if (record.getSerialNumber() != null) {
+ sql.VALUES("Serial_Number", "#{serialNumber,jdbcType=BIGINT}");
+ }
+
+ if (record.getApplicationNumber() != null) {
+ sql.VALUES("Application_Number", "#{applicationNumber,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getCallId() != null) {
+ sql.VALUES("Call_Id", "#{callId,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getImageId() != null) {
+ sql.VALUES("Image_Id", "#{imageId,jdbcType=NVARCHAR}");
+ }
+
+
+ if (record.getDownloadStatus() != null) {
+ sql.VALUES("Download_Status", "#{downloadStatus,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getEntryTime() != null) {
+ sql.VALUES("Entry_Time", "#{entryTime,jdbcType=TIMESTAMP}");
+ }
+
+ if (record.getInvokeTime() != null) {
+ sql.VALUES("Invoke_Time", "#{invokeTime,jdbcType=TIMESTAMP}");
+ }
+
+ if (record.getRetryCount() != null) {
+ sql.VALUES("Retry_Count", "#{retryCount,jdbcType=INTEGER}");
+ }
+
+ if (record.getMaxRetry() != null) {
+ sql.VALUES("Max_Retry", "#{maxRetry,jdbcType=INTEGER}");
+ }
+
+ if (record.getInvokePriority() != null) {
+ sql.VALUES("Invoke_Priority", "#{invokePriority,jdbcType=INTEGER}");
+ }
+
+ if (record.getErrorMessage() != null) {
+ sql.VALUES("Error_Message", "#{errorMessage,jdbcType=NVARCHAR}");
+ }
+
+ return sql.toString();
+ }
+
+ /**
+ * @Description 根据主键选择对象中的非空字段更新表中记录
+ * @param record
+ * @return java.lang.String
+ */
+ public String updateByPrimaryKeySelective(RecordingPendingDownloadQueueDO record) {
+ SQL sql = new SQL();
+ sql.UPDATE("Recording_Pending_Download_Queue");
+
+ if (record.getApplicationNumber() != null) {
+ sql.SET("Application_Number = #{applicationNumber,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getCallId() != null) {
+ sql.SET("Call_Id = #{callId,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getImageId() != null) {
+ sql.SET("Image_Id = #{imageId,jdbcType=NVARCHAR}");
+ }
+
+
+ if (record.getDownloadStatus() != null) {
+ sql.SET("Download_Status = #{downloadStatus,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getEntryTime() != null) {
+ sql.SET("Entry_Time = #{entryTime,jdbcType=TIMESTAMP}");
+ }
+
+ if (record.getInvokeTime() != null) {
+ sql.SET("Invoke_Time = #{invokeTime,jdbcType=TIMESTAMP}");
+ }
+
+ if (record.getRetryCount() != null) {
+ sql.SET("Retry_Count = #{retryCount,jdbcType=INTEGER}");
+ }
+
+ if (record.getMaxRetry() != null) {
+ sql.SET("Max_Retry = #{maxRetry,jdbcType=INTEGER}");
+ }
+
+ if (record.getInvokePriority() != null) {
+ sql.SET("Invoke_Priority = #{invokePriority,jdbcType=INTEGER}");
+ }
+
+ if (record.getErrorMessage() != null) {
+ sql.SET("Error_Message = #{errorMessage,jdbcType=NVARCHAR}");
+ }
+
+ sql.WHERE("Serial_Number = #{serialNumber,jdbcType=BIGINT}");
+
+ return sql.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/gbg/activate/video/mapper/VideoSigningDownloadRecordMapper.java b/src/main/java/com/gbg/activate/video/mapper/VideoSigningDownloadRecordMapper.java
new file mode 100644
index 0000000..f8545ba
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/mapper/VideoSigningDownloadRecordMapper.java
@@ -0,0 +1,151 @@
+package com.gbg.activate.video.mapper;
+
+import com.gbg.activate.video.entity.VideoSigningDownloadRecordDO;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Delete;
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.InsertProvider;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Result;
+import org.apache.ibatis.annotations.ResultMap;
+import org.apache.ibatis.annotations.Results;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+import org.apache.ibatis.annotations.UpdateProvider;
+import org.apache.ibatis.type.JdbcType;
+
+@Mapper
+public interface VideoSigningDownloadRecordMapper {
+ /**
+ * @Description 根据主键删除表中记录
+ * @param applicationNumber
+ * @param imageId
+ * @return int
+ */
+ @Delete({
+ "delete from Video_Signing_Download_Record",
+ "where Application_Number = #{applicationNumber,jdbcType=NVARCHAR}",
+ "and Image_Id = #{imageId,jdbcType=NVARCHAR}"
+ })
+ int deleteByPrimaryKey(@Param("applicationNumber") String applicationNumber, @Param("imageId") String imageId);
+
+ /**
+ * @Description 向表中插入新记录
+ * @param record
+ * @return int
+ */
+ @Insert({
+ "insert into Video_Signing_Download_Record (Application_Number, Image_Id, ",
+ "Image_Name, Image_Type, ",
+ "Image_Size, Image_Url, ",
+ "Video_Duration, Create_Time, ",
+ "Download_Time)",
+ "values (#{applicationNumber,jdbcType=NVARCHAR}, #{imageId,jdbcType=NVARCHAR}, ",
+ "#{imageName,jdbcType=NVARCHAR}, #{imageType,jdbcType=NVARCHAR}, ",
+ "#{imageSize,jdbcType=NVARCHAR}, #{imageUrl,jdbcType=NVARCHAR}, ",
+ "#{videoDuration,jdbcType=NVARCHAR}, #{createTime,jdbcType=NVARCHAR}, ",
+ "#{downloadTime,jdbcType=TIMESTAMP})"
+ })
+ int insert(VideoSigningDownloadRecordDO record);
+
+ /**
+ * @Description 选择对象中的非空字段向表中插入新记录
+ * @param record
+ * @return int
+ */
+ @InsertProvider(type=VideoSigningDownloadRecordSqlProvider.class, method="insertSelective")
+ int insertSelective(VideoSigningDownloadRecordDO record);
+
+ /**
+ * @Description 根据主键查询表中记录
+ * @param applicationNumber
+ * @param imageId
+ * @return com.gbg.activate.entity.dao.VideoSigningDownloadRecordDO
+ */
+ @Select({
+ "select",
+ "Application_Number, Image_Id, Image_Name, Image_Type, Image_Size, Image_Url, ",
+ "Video_Duration, Create_Time, Download_Time",
+ "from Video_Signing_Download_Record",
+ "where Application_Number = #{applicationNumber,jdbcType=NVARCHAR}",
+ "and Image_Id = #{imageId,jdbcType=NVARCHAR}"
+ })
+ @Results(id="VideoSigningDownloadRecordMap", value={
+ @Result(column="Application_Number", property="applicationNumber", jdbcType=JdbcType.NVARCHAR, id=true),
+ @Result(column="Image_Id", property="imageId", jdbcType=JdbcType.NVARCHAR, id=true),
+ @Result(column="Image_Name", property="imageName", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Image_Type", property="imageType", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Image_Size", property="imageSize", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Image_Url", property="imageUrl", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Video_Duration", property="videoDuration", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Create_Time", property="createTime", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Download_Time", property="downloadTime", jdbcType=JdbcType.TIMESTAMP)
+ })
+ VideoSigningDownloadRecordDO selectByPrimaryKey(@Param("applicationNumber") String applicationNumber, @Param("imageId") String imageId);
+
+ /**
+ * @Description 根据主键选择对象中的非空字段更新表中记录
+ * @param record
+ * @return int
+ */
+ @UpdateProvider(type=VideoSigningDownloadRecordSqlProvider.class, method="updateByPrimaryKeySelective")
+ int updateByPrimaryKeySelective(VideoSigningDownloadRecordDO record);
+
+ /**
+ * @Description 根据主键更新表中记录
+ * @param record
+ * @return int
+ */
+ @Update({
+ "update Video_Signing_Download_Record",
+ "set Image_Name = #{imageName,jdbcType=NVARCHAR},",
+ "Image_Type = #{imageType,jdbcType=NVARCHAR},",
+ "Image_Size = #{imageSize,jdbcType=NVARCHAR},",
+ "Image_Url = #{imageUrl,jdbcType=NVARCHAR},",
+ "Video_Duration = #{videoDuration,jdbcType=NVARCHAR},",
+ "Create_Time = #{createTime,jdbcType=NVARCHAR},",
+ "Download_Time = #{downloadTime,jdbcType=TIMESTAMP}",
+ "where Application_Number = #{applicationNumber,jdbcType=NVARCHAR}",
+ "and Image_Id = #{imageId,jdbcType=NVARCHAR}"
+ })
+ int updateByPrimaryKey(VideoSigningDownloadRecordDO record);
+
+ /**
+ * @Title: deleteByApplicationNumber
+ * @Description: 根据申请编号删除记录
+ * @param applicationNumber
+ * @return 参数
+ * @return int 返回类型
+ * @throws
+ * @author Frank.Wang@gbgplc.com
+ * @date 2025-07-18 05:35:37
+ */
+ @Delete({
+ "DELETE FROM Video_Signing_Download_Record WITH(ROWLOCK)",
+ "WHERE Application_Number = #{applicationNumber,jdbcType=NVARCHAR}"
+ })
+ int deleteByApplicationNumber(@Param("applicationNumber") String applicationNumber);
+
+ /**
+ * @Title: listExpiredRecords
+ * @Description: 列出过期的文件记录
+ * @param validDays
+ * @return 参数
+ * @return List 返回类型
+ * @throws
+ * @author Frank.Wang@gbgplc.com
+ * @date 2025-08-08 06:13:30
+ */
+ @Select({
+ "SELECT",
+ "Application_Number, Image_Id, Image_Name, Image_Type, Image_Size, Image_Url, ",
+ "Video_Duration, Create_Time, Download_Time",
+ "FROM Video_Signing_Download_Record WITH(NOLOCK)",
+ "WHERE Download_Time < DATEADD(DAY, -#{validDays,jdbcType=INTEGER}, CAST(GETDATE() AS date))"
+ })
+ @ResultMap("VideoSigningDownloadRecordMap")
+ List listExpiredRecords(@Param("validDays") Integer validDays);
+}
\ No newline at end of file
diff --git a/src/main/java/com/gbg/activate/video/mapper/VideoSigningDownloadRecordSqlProvider.java b/src/main/java/com/gbg/activate/video/mapper/VideoSigningDownloadRecordSqlProvider.java
new file mode 100644
index 0000000..e0ea4b8
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/mapper/VideoSigningDownloadRecordSqlProvider.java
@@ -0,0 +1,98 @@
+package com.gbg.activate.video.mapper;
+
+import com.gbg.activate.video.entity.VideoSigningDownloadRecordDO;
+import org.apache.ibatis.jdbc.SQL;
+
+public class VideoSigningDownloadRecordSqlProvider {
+
+ /**
+ * @Description 选择对象中的非空字段向表中插入新记录
+ * @param record
+ * @return java.lang.String
+ */
+ public String insertSelective(VideoSigningDownloadRecordDO record) {
+ SQL sql = new SQL();
+ sql.INSERT_INTO("Video_Signing_Download_Record");
+
+ if (record.getApplicationNumber() != null) {
+ sql.VALUES("Application_Number", "#{applicationNumber,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getImageId() != null) {
+ sql.VALUES("Image_Id", "#{imageId,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getImageName() != null) {
+ sql.VALUES("Image_Name", "#{imageName,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getImageType() != null) {
+ sql.VALUES("Image_Type", "#{imageType,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getImageSize() != null) {
+ sql.VALUES("Image_Size", "#{imageSize,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getImageUrl() != null) {
+ sql.VALUES("Image_Url", "#{imageUrl,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getVideoDuration() != null) {
+ sql.VALUES("Video_Duration", "#{videoDuration,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getCreateTime() != null) {
+ sql.VALUES("Create_Time", "#{createTime,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getDownloadTime() != null) {
+ sql.VALUES("Download_Time", "#{downloadTime,jdbcType=TIMESTAMP}");
+ }
+
+ return sql.toString();
+ }
+
+ /**
+ * @Description 根据主键选择对象中的非空字段更新表中记录
+ * @param record
+ * @return java.lang.String
+ */
+ public String updateByPrimaryKeySelective(VideoSigningDownloadRecordDO record) {
+ SQL sql = new SQL();
+ sql.UPDATE("Video_Signing_Download_Record");
+
+ if (record.getImageName() != null) {
+ sql.SET("Image_Name = #{imageName,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getImageType() != null) {
+ sql.SET("Image_Type = #{imageType,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getImageSize() != null) {
+ sql.SET("Image_Size = #{imageSize,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getImageUrl() != null) {
+ sql.SET("Image_Url = #{imageUrl,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getVideoDuration() != null) {
+ sql.SET("Video_Duration = #{videoDuration,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getCreateTime() != null) {
+ sql.SET("Create_Time = #{createTime,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getDownloadTime() != null) {
+ sql.SET("Download_Time = #{downloadTime,jdbcType=TIMESTAMP}");
+ }
+
+ sql.WHERE("Application_Number = #{applicationNumber,jdbcType=NVARCHAR}");
+ sql.WHERE("Image_Id = #{imageId,jdbcType=NVARCHAR}");
+
+ return sql.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/gbg/activate/video/mapper/VideoSigningPendingDownloadQueueMapper.java b/src/main/java/com/gbg/activate/video/mapper/VideoSigningPendingDownloadQueueMapper.java
new file mode 100644
index 0000000..f0c338b
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/mapper/VideoSigningPendingDownloadQueueMapper.java
@@ -0,0 +1,136 @@
+package com.gbg.activate.video.mapper;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Delete;
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.InsertProvider;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Result;
+import org.apache.ibatis.annotations.ResultMap;
+import org.apache.ibatis.annotations.Results;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+import org.apache.ibatis.annotations.UpdateProvider;
+import org.apache.ibatis.type.JdbcType;
+
+import com.gbg.activate.video.entity.VideoSigningPendingDownloadQueueDO;
+
+@Mapper
+public interface VideoSigningPendingDownloadQueueMapper {
+ /**
+ * @Description 根据主键删除表中记录
+ * @param serialNumber
+ * @return int
+ */
+ @Delete({
+ "delete from Video_Signing_Pending_Download_Queue",
+ "where Serial_Number = #{serialNumber,jdbcType=BIGINT}"
+ })
+ int deleteByPrimaryKey(Long serialNumber);
+
+ /**
+ * @Description 向表中插入新记录
+ * @param record
+ * @return int
+ */
+ @Insert({
+ "insert into Video_Signing_Pending_Download_Queue (Serial_Number, Application_Number, ",
+ "Trade_Number, Customer_Number, ",
+ "Download_Status, Entry_Time, ",
+ "Invoke_Time, Retry_Count, ",
+ "Max_Retry, Invoke_Priority, ",
+ "Error_Message)",
+ "values (#{serialNumber,jdbcType=BIGINT}, #{applicationNumber,jdbcType=NVARCHAR}, ",
+ "#{tradeNumber,jdbcType=NVARCHAR}, #{customerNumber,jdbcType=NVARCHAR}, ",
+ "#{downloadStatus,jdbcType=NVARCHAR}, #{entryTime,jdbcType=TIMESTAMP}, ",
+ "#{invokeTime,jdbcType=TIMESTAMP}, #{retryCount,jdbcType=INTEGER}, ",
+ "#{maxRetry,jdbcType=INTEGER}, #{invokePriority,jdbcType=INTEGER}, ",
+ "#{errorMessage,jdbcType=NVARCHAR})"
+ })
+ int insert(VideoSigningPendingDownloadQueueDO record);
+
+ /**
+ * @Description 选择对象中的非空字段向表中插入新记录
+ * @param record
+ * @return int
+ */
+ @InsertProvider(type=VideoSigningPendingDownloadQueueSqlProvider.class, method="insertSelective")
+ int insertSelective(VideoSigningPendingDownloadQueueDO record);
+
+ /**
+ * @Description 根据主键查询表中记录
+ * @param serialNumber
+ * @return com.gbg.activate.entity.dao.VideoSigningPendingDownloadQueueDO
+ */
+ @Select({
+ "select",
+ "Serial_Number, Application_Number, Trade_Number, Customer_Number, Download_Status, ",
+ "Entry_Time, Invoke_Time, Retry_Count, Max_Retry, Invoke_Priority, Error_Message",
+ "from Video_Signing_Pending_Download_Queue",
+ "where Serial_Number = #{serialNumber,jdbcType=BIGINT}"
+ })
+ @Results(id="VideoSigningPendingDownloadQueueMap", value={
+ @Result(column="Serial_Number", property="serialNumber", jdbcType=JdbcType.BIGINT, id=true),
+ @Result(column="Application_Number", property="applicationNumber", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Trade_Number", property="tradeNumber", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Customer_Number", property="customerNumber", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Download_Status", property="downloadStatus", jdbcType=JdbcType.NVARCHAR),
+ @Result(column="Entry_Time", property="entryTime", jdbcType=JdbcType.TIMESTAMP),
+ @Result(column="Invoke_Time", property="invokeTime", jdbcType=JdbcType.TIMESTAMP),
+ @Result(column="Retry_Count", property="retryCount", jdbcType=JdbcType.INTEGER),
+ @Result(column="Max_Retry", property="maxRetry", jdbcType=JdbcType.INTEGER),
+ @Result(column="Invoke_Priority", property="invokePriority", jdbcType=JdbcType.INTEGER),
+ @Result(column="Error_Message", property="errorMessage", jdbcType=JdbcType.NVARCHAR)
+ })
+ VideoSigningPendingDownloadQueueDO selectByPrimaryKey(Long serialNumber);
+
+ /**
+ * @Description 根据主键选择对象中的非空字段更新表中记录
+ * @param record
+ * @return int
+ */
+ @UpdateProvider(type=VideoSigningPendingDownloadQueueSqlProvider.class, method="updateByPrimaryKeySelective")
+ int updateByPrimaryKeySelective(VideoSigningPendingDownloadQueueDO record);
+
+ /**
+ * @Description 根据主键更新表中记录
+ * @param record
+ * @return int
+ */
+ @Update({
+ "update Video_Signing_Pending_Download_Queue",
+ "set Application_Number = #{applicationNumber,jdbcType=NVARCHAR},",
+ "Trade_Number = #{tradeNumber,jdbcType=NVARCHAR},",
+ "Customer_Number = #{customerNumber,jdbcType=NVARCHAR},",
+ "Download_Status = #{downloadStatus,jdbcType=NVARCHAR},",
+ "Entry_Time = #{entryTime,jdbcType=TIMESTAMP},",
+ "Invoke_Time = #{invokeTime,jdbcType=TIMESTAMP},",
+ "Retry_Count = #{retryCount,jdbcType=INTEGER},",
+ "Max_Retry = #{maxRetry,jdbcType=INTEGER},",
+ "Invoke_Priority = #{invokePriority,jdbcType=INTEGER},",
+ "Error_Message = #{errorMessage,jdbcType=NVARCHAR}",
+ "where Serial_Number = #{serialNumber,jdbcType=BIGINT}"
+ })
+ int updateByPrimaryKey(VideoSigningPendingDownloadQueueDO record);
+
+ /**
+ * @Title: fetchPendingTasks
+ * @Description: 获取待下载的任务列表
+ * @return 参数
+ * @return List 返回类型
+ * @throws
+ * @author Frank.Wang@gbgplc.com
+ * @date 2025-07-15 05:52:16
+ */
+ @Select({
+ "SELECT TOP (100)",
+ "Serial_Number, Application_Number, Trade_Number, Customer_Number, Download_Status, ",
+ "Entry_Time, Invoke_Time, Retry_Count, Max_Retry, Invoke_Priority, Error_Message",
+ "FROM Video_Signing_Pending_Download_Queue WITH(NOLOCK)",
+ "WHERE Download_Status = 'PENDING'",
+ "ORDER BY Invoke_Priority DESC"
+ })
+ @ResultMap("VideoSigningPendingDownloadQueueMap")
+ List fetchPendingTasks();
+}
\ No newline at end of file
diff --git a/src/main/java/com/gbg/activate/video/mapper/VideoSigningPendingDownloadQueueSqlProvider.java b/src/main/java/com/gbg/activate/video/mapper/VideoSigningPendingDownloadQueueSqlProvider.java
new file mode 100644
index 0000000..f2d689d
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/mapper/VideoSigningPendingDownloadQueueSqlProvider.java
@@ -0,0 +1,118 @@
+package com.gbg.activate.video.mapper;
+
+import org.apache.ibatis.jdbc.SQL;
+
+import com.gbg.activate.video.entity.VideoSigningPendingDownloadQueueDO;
+
+public class VideoSigningPendingDownloadQueueSqlProvider {
+
+ /**
+ * @Description 选择对象中的非空字段向表中插入新记录
+ * @param record
+ * @return java.lang.String
+ */
+ public String insertSelective(VideoSigningPendingDownloadQueueDO record) {
+ SQL sql = new SQL();
+ sql.INSERT_INTO("Video_Signing_Pending_Download_Queue");
+
+ if (record.getSerialNumber() != null) {
+ sql.VALUES("Serial_Number", "#{serialNumber,jdbcType=BIGINT}");
+ }
+
+ if (record.getApplicationNumber() != null) {
+ sql.VALUES("Application_Number", "#{applicationNumber,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getTradeNumber() != null) {
+ sql.VALUES("Trade_Number", "#{tradeNumber,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getCustomerNumber() != null) {
+ sql.VALUES("Customer_Number", "#{customerNumber,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getDownloadStatus() != null) {
+ sql.VALUES("Download_Status", "#{downloadStatus,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getEntryTime() != null) {
+ sql.VALUES("Entry_Time", "#{entryTime,jdbcType=TIMESTAMP}");
+ }
+
+ if (record.getInvokeTime() != null) {
+ sql.VALUES("Invoke_Time", "#{invokeTime,jdbcType=TIMESTAMP}");
+ }
+
+ if (record.getRetryCount() != null) {
+ sql.VALUES("Retry_Count", "#{retryCount,jdbcType=INTEGER}");
+ }
+
+ if (record.getMaxRetry() != null) {
+ sql.VALUES("Max_Retry", "#{maxRetry,jdbcType=INTEGER}");
+ }
+
+ if (record.getInvokePriority() != null) {
+ sql.VALUES("Invoke_Priority", "#{invokePriority,jdbcType=INTEGER}");
+ }
+
+ if (record.getErrorMessage() != null) {
+ sql.VALUES("Error_Message", "#{errorMessage,jdbcType=NVARCHAR}");
+ }
+
+ return sql.toString();
+ }
+
+ /**
+ * @Description 根据主键选择对象中的非空字段更新表中记录
+ * @param record
+ * @return java.lang.String
+ */
+ public String updateByPrimaryKeySelective(VideoSigningPendingDownloadQueueDO record) {
+ SQL sql = new SQL();
+ sql.UPDATE("Video_Signing_Pending_Download_Queue");
+
+ if (record.getApplicationNumber() != null) {
+ sql.SET("Application_Number = #{applicationNumber,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getTradeNumber() != null) {
+ sql.SET("Trade_Number = #{tradeNumber,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getCustomerNumber() != null) {
+ sql.SET("Customer_Number = #{customerNumber,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getDownloadStatus() != null) {
+ sql.SET("Download_Status = #{downloadStatus,jdbcType=NVARCHAR}");
+ }
+
+ if (record.getEntryTime() != null) {
+ sql.SET("Entry_Time = #{entryTime,jdbcType=TIMESTAMP}");
+ }
+
+ if (record.getInvokeTime() != null) {
+ sql.SET("Invoke_Time = #{invokeTime,jdbcType=TIMESTAMP}");
+ }
+
+ if (record.getRetryCount() != null) {
+ sql.SET("Retry_Count = #{retryCount,jdbcType=INTEGER}");
+ }
+
+ if (record.getMaxRetry() != null) {
+ sql.SET("Max_Retry = #{maxRetry,jdbcType=INTEGER}");
+ }
+
+ if (record.getInvokePriority() != null) {
+ sql.SET("Invoke_Priority = #{invokePriority,jdbcType=INTEGER}");
+ }
+
+ if (record.getErrorMessage() != null) {
+ sql.SET("Error_Message = #{errorMessage,jdbcType=NVARCHAR}");
+ }
+
+ sql.WHERE("Serial_Number = #{serialNumber,jdbcType=BIGINT}");
+
+ return sql.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/gbg/activate/video/service/AudioFileCleanupServiceImpl.java b/src/main/java/com/gbg/activate/video/service/AudioFileCleanupServiceImpl.java
new file mode 100644
index 0000000..1fe7194
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/service/AudioFileCleanupServiceImpl.java
@@ -0,0 +1,113 @@
+package com.gbg.activate.video.service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.time.Instant;
+import java.util.concurrent.atomic.AtomicInteger;
+
+@Service
+public class AudioFileCleanupServiceImpl implements IAudioFileCleanupService {
+ private static final Logger LOG = LoggerFactory.getLogger(AudioFileCleanupServiceImpl.class);
+
+ @Value("${audio.cleanup.nas-path:/data/nas}")
+ private String nasPath;
+
+ @Value("${audio.cleanup.retention-days:30}")
+ private int retentionDays;
+
+ @Value("${audio.cleanup.enabled:true}")
+ private boolean enabled;
+
+
+ @Override
+ public int cleanupOldAudioFiles() {
+ if (!enabled) {
+ LOG.info("录音文件清理功能已禁用");
+ return 0;
+ }
+
+
+ Path cleanupPath = Paths.get(nasPath);
+ LOG.info("开始清理录音文件,路径: {}, 保留天数: {}", cleanupPath, retentionDays);
+
+ if (!Files.exists(cleanupPath)) {
+ LOG.warn("录音文件路径不存在: {}", cleanupPath);
+ return 0;
+ }
+
+ if (!Files.isDirectory(cleanupPath)) {
+ LOG.error("录音文件路径不是目录: {}", cleanupPath);
+ return 0;
+ }
+
+ // 计算过期时间
+ Instant cutoffTime = Instant.now().minusSeconds(retentionDays * 24L * 3600);
+ AtomicInteger deletedCount = new AtomicInteger(0);
+
+ try {
+ Files.walkFileTree(cleanupPath, new SimpleFileVisitor() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ // 只处理音频文件
+ if (isAudioFile(file)) {
+ try {
+ Instant lastModified = Files.getLastModifiedTime(file).toInstant();
+
+ if (lastModified.isBefore(cutoffTime)) {
+ // 删除文件
+ boolean deleted = Files.deleteIfExists(file);
+ if (deleted) {
+ deletedCount.incrementAndGet();
+ LOG.debug("已删除过期录音文件: {}", file);
+
+ }
+ }
+ } catch (Exception e) {
+ LOG.error("处理文件失败: {}, 错误: {}", file, e.getMessage());
+ }
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(Path file, IOException exc) {
+ LOG.warn("无法访问文件: {}, 原因: {}", file, exc.getMessage());
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+ });
+
+ LOG.info("录音文件清理完成,共删除 {} 个文件", deletedCount.get());
+
+ } catch (IOException e) {
+ LOG.error("遍历目录时发生错误: {}", e.getMessage(), e);
+ }
+
+ return deletedCount.get();
+ }
+
+ /**
+ * 判断是否为音频文件
+ */
+ private boolean isAudioFile(Path file) {
+ String fileName = file.getFileName().toString().toLowerCase();
+ return fileName.endsWith(".mp3")
+ || fileName.endsWith(".wav")
+ || fileName.endsWith(".ogg")
+ || fileName.endsWith(".flac")
+ || fileName.endsWith(".m4a")
+ || fileName.endsWith(".aac")
+ || fileName.endsWith(".amr");
+ }
+
+}
diff --git a/src/main/java/com/gbg/activate/video/service/ClearExpiredFileServiceImpl.java b/src/main/java/com/gbg/activate/video/service/ClearExpiredFileServiceImpl.java
new file mode 100644
index 0000000..c1e1307
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/service/ClearExpiredFileServiceImpl.java
@@ -0,0 +1,40 @@
+package com.gbg.activate.video.service;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.gbg.activate.video.config.ImageSdkParams;
+import com.gbg.activate.video.entity.VideoSigningDownloadRecordDO;
+import com.gbg.activate.video.mapper.VideoSigningDownloadRecordMapper;
+
+@Service
+public class ClearExpiredFileServiceImpl implements IClearExpiredFileService {
+ private static final Logger LOG = LoggerFactory.getLogger(ClearExpiredFileServiceImpl.class);
+
+ @Autowired
+ private ImageSdkParams params;
+ @Autowired
+ private VideoSigningDownloadRecordMapper recordMapper;
+
+ @Override
+ public void clearExpiredFiles() {
+ List records = recordMapper.listExpiredRecords(params.getValidDays());
+ for (VideoSigningDownloadRecordDO record : records) {
+ try {
+ Path filePath = Paths.get(params.getFileSavePath()).resolve(record.getImageName()).normalize();
+ filePath.toFile().delete();
+ recordMapper.deleteByPrimaryKey(record.getApplicationNumber(), record.getImageId());
+ LOG.info("Delete Expired File:{}, {} Success", record.getApplicationNumber(), record.getImageName());
+ } catch (Exception error) {
+ LOG.error("Delete Expired File:{}, {}", record.getApplicationNumber(), record.getImageName());
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/com/gbg/activate/video/service/DownloadRecordingTaskServiceImpl.java b/src/main/java/com/gbg/activate/video/service/DownloadRecordingTaskServiceImpl.java
new file mode 100644
index 0000000..b6c51a3
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/service/DownloadRecordingTaskServiceImpl.java
@@ -0,0 +1,101 @@
+package com.gbg.activate.video.service;
+
+import com.gbg.activate.video.config.ImageSdkParams;
+import com.gbg.activate.video.constant.DownloadStatus;
+import com.gbg.activate.video.entity.RecordingDownloadDO;
+import com.gbg.activate.video.entity.RecordingPendingDownloadQueueDO;
+import com.gbg.activate.video.mapper.RecordingDownloadMapper;
+import com.gbg.activate.video.mapper.RecordingPendingDownloadQueueMapper;
+import com.icms.common.bean.SdkImage;
+import com.icms.common.bean.SdkResult;
+import com.icms.sdk.inter.ImageSdkInter;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.util.UriComponentsBuilder;
+import java.util.Date;
+import java.util.List;
+
+@Service
+public class DownloadRecordingTaskServiceImpl implements IDownloadRecordingTaskService {
+ private static final Logger LOG = LoggerFactory.getLogger(DownloadRecordingTaskServiceImpl.class);
+
+ @Value("${server.address}")
+ private String serverAddress;
+ @Value("${record.server.port}")
+ private String serverPort;
+ @Autowired
+ private ImageSdkParams params;
+ @Autowired
+ private RecordingPendingDownloadQueueMapper taskMapper;
+ @Autowired
+ private RecordingDownloadMapper recordMapper;
+ @Autowired
+ private ImageSdkInter imageService;
+
+ @Override
+ public void processPendingTasks() {
+ List tasks = taskMapper.fetchPendingTasks();
+
+ for (RecordingPendingDownloadQueueDO task : tasks) {
+ try {
+ processSingleTask(task);
+ } catch (Exception e) {
+ LOG.error("处理下载任务失败: {}", task.getApplicationNumber(), e);
+ handleFailedTask(task, e.getMessage());
+ }
+ }
+ }
+
+ private void processSingleTask(RecordingPendingDownloadQueueDO task) throws Exception {
+
+ if (ObjectUtils.allNull(task)){
+ return;
+ }
+ if (task.getImageId() == null || "".equals(task.getImageId()) || StringUtils.isBlank(task.getImageId())){
+ LOG.info("录音id是空");
+ return;
+ }
+
+ // 1. 更新任务状态为下载中
+ task.setDownloadStatus(DownloadStatus.DOWNLOADING);
+ task.setInvokeTime(new Date());
+ taskMapper.updateByPrimaryKeySelective(task);
+
+ // 2. 下载文件
+ SdkResult result = imageService.downloadOnePageBigImageByImageId(params.getSysNo1(), task.getImageId(), params.getFileSavePath1());
+ if (!StringUtils.equals(result.getRetCode(), "00000")) {
+ throw new Exception(result.getRetMessage());
+ }
+ //recordMapper.deleteByApplicationNumber(task.getApplicationNumber());
+ for (SdkImage image: result.getSdkImages()) {
+ RecordingDownloadDO record = new RecordingDownloadDO();
+ record.setApplicationNumber(task.getApplicationNumber());
+ record.setCallId(task.getCallId());
+ record.setImageId(image.getImageId());
+ record.setImageName(image.getImageName());
+ record.setImageType(StringUtils.substringAfter(image.getImageName(), "."));
+ String url = UriComponentsBuilder.newInstance().scheme("http").host(serverAddress).port(serverPort).pathSegment("audio", image.getImageName()).build().toUriString();
+ record.setImageUrl(url);
+ record.setImageSize(image.getImageSize());
+ record.setCreateTime(image.getCreateDate());
+ record.setDownloadTime(new Date());
+ recordMapper.insert(record);
+ }
+ //taskMapper.deleteByPrimaryKey(task.getSerialNumber());
+ }
+
+ private void handleFailedTask(RecordingPendingDownloadQueueDO task, String errorMsg) {
+ if (task.getRetryCount() >= task.getMaxRetry()) {
+ task.setDownloadStatus(DownloadStatus.FAILED);
+ } else {
+ task.setRetryCount(task.getRetryCount() + 1);
+ }
+ task.setErrorMessage(StringUtils.left(errorMsg, 500));
+ taskMapper.updateByPrimaryKeySelective(task);
+ }
+}
diff --git a/src/main/java/com/gbg/activate/video/service/DownloadTaskServiceImpl.java b/src/main/java/com/gbg/activate/video/service/DownloadTaskServiceImpl.java
new file mode 100644
index 0000000..4068dbe
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/service/DownloadTaskServiceImpl.java
@@ -0,0 +1,116 @@
+package com.gbg.activate.video.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.parser.ParseContext;
+import org.apache.tika.parser.Parser;
+import org.apache.tika.parser.mp4.MP4Parser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.util.UriComponentsBuilder;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import com.gbg.activate.video.config.ImageSdkParams;
+import com.gbg.activate.video.constant.DownloadStatus;
+import com.gbg.activate.video.entity.VideoSigningDownloadRecordDO;
+import com.gbg.activate.video.entity.VideoSigningPendingDownloadQueueDO;
+import com.gbg.activate.video.mapper.VideoSigningDownloadRecordMapper;
+import com.gbg.activate.video.mapper.VideoSigningPendingDownloadQueueMapper;
+import com.icms.common.bean.SdkImage;
+import com.icms.common.bean.SdkResult;
+import com.icms.sdk.inter.ImageSdkInter;
+
+@Service
+public class DownloadTaskServiceImpl implements IDownloadTaskService {
+ private static final Logger LOG = LoggerFactory.getLogger(DownloadTaskServiceImpl.class);
+
+ @Value("${server.address}")
+ private String serverAddress;
+ @Value("${server.port}")
+ private String serverPort;
+ @Autowired
+ private ImageSdkParams params;
+ @Autowired
+ private VideoSigningPendingDownloadQueueMapper taskMapper;
+ @Autowired
+ private VideoSigningDownloadRecordMapper recordMapper;
+ @Autowired
+ private ImageSdkInter imageService;
+
+ @Override
+ public void processPendingTasks() {
+ List tasks = taskMapper.fetchPendingTasks();
+
+ for (VideoSigningPendingDownloadQueueDO task : tasks) {
+ try {
+ processSingleTask(task);
+ } catch (Exception e) {
+ LOG.error("处理下载任务失败: {}", task.getApplicationNumber(), e);
+ handleFailedTask(task, e.getMessage());
+ }
+ }
+ }
+
+ private void processSingleTask(VideoSigningPendingDownloadQueueDO task) throws Exception {
+ // 1. 更新任务状态为下载中
+ task.setDownloadStatus(DownloadStatus.DOWNLOADING);
+ task.setInvokeTime(new Date());
+ taskMapper.updateByPrimaryKeySelective(task);
+
+ // 2. 下载文件
+ recordMapper.deleteByApplicationNumber(task.getApplicationNumber());
+ SdkResult result = imageService.downloadOneStoreBigImageByTradeNo(params.getSysNo(), task.getTradeNumber(), task.getCustomerNumber(), params.getFileSavePath());
+ if (!StringUtils.equals(result.getRetCode(), "00000")) {
+ throw new Exception(result.getRetMessage());
+ }
+ for (SdkImage image : result.getSdkImages()) {
+ VideoSigningDownloadRecordDO record = new VideoSigningDownloadRecordDO();
+ record.setApplicationNumber(task.getApplicationNumber());
+ record.setImageId(image.getImageId());
+ record.setImageName(image.getImageName());
+ record.setImageType(StringUtils.substringAfter(image.getImageName(), "."));
+ record.setImageSize(image.getImageSize());
+ String url = UriComponentsBuilder.newInstance().scheme("http").host(serverAddress).port(serverPort).pathSegment("videos", image.getImageName()).build().toUriString();
+ record.setImageUrl(url);
+ record.setCreateTime(image.getCreateDate());
+ record.setDownloadTime(new Date());
+ record.setVideoDuration(StringUtils.EMPTY);
+ if (StringUtils.endsWith(image.getImageName(), "mp4")) {
+ Path filePath = Paths.get(params.getFileSavePath()).resolve(image.getImageName()).normalize();
+ try (InputStream stream = Files.newInputStream(filePath)) {
+ Metadata metadata = new Metadata();
+ Parser parser = new MP4Parser();
+ parser.parse(stream, new DefaultHandler(), metadata, new ParseContext());
+ record.setVideoDuration(metadata.get("xmpDM:duration"));
+ } catch (IOException | SAXException | TikaException error) {
+ LOG.error("Duration Error", error);
+ }
+ }
+ recordMapper.insert(record);
+ }
+ taskMapper.deleteByPrimaryKey(task.getSerialNumber());
+ }
+
+ private void handleFailedTask(VideoSigningPendingDownloadQueueDO task, String errorMsg) {
+ if (task.getRetryCount() >= task.getMaxRetry()) {
+ task.setDownloadStatus(DownloadStatus.FAILED);
+ } else {
+ task.setRetryCount(task.getRetryCount() + 1);
+ }
+ task.setErrorMessage(StringUtils.left(errorMsg, 500));
+ taskMapper.updateByPrimaryKeySelective(task);
+ }
+}
diff --git a/src/main/java/com/gbg/activate/video/service/IAudioFileCleanupService.java b/src/main/java/com/gbg/activate/video/service/IAudioFileCleanupService.java
new file mode 100644
index 0000000..9aaf09b
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/service/IAudioFileCleanupService.java
@@ -0,0 +1,13 @@
+package com.gbg.activate.video.service;
+
+public interface IAudioFileCleanupService {
+ /**
+ * @Title: processPendingTasks
+ * @Description: 删除文件夹中的文件
+ * @return void 返回类型
+ * @throws
+ * @author Frank.Wang@gbgplc.com
+ * @date 2025-07-15 03:15:08
+ */
+ int cleanupOldAudioFiles();
+}
diff --git a/src/main/java/com/gbg/activate/video/service/IClearExpiredFileService.java b/src/main/java/com/gbg/activate/video/service/IClearExpiredFileService.java
new file mode 100644
index 0000000..cb618ce
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/service/IClearExpiredFileService.java
@@ -0,0 +1,13 @@
+package com.gbg.activate.video.service;
+
+public interface IClearExpiredFileService {
+ /**
+ * @Title: clearExpiredFiles
+ * @Description: 清理过期的文件
+ * @return void 返回类型
+ * @throws
+ * @author Frank.Wang@gbgplc.com
+ * @date 2025-08-08 05:45:53
+ */
+ void clearExpiredFiles();
+}
diff --git a/src/main/java/com/gbg/activate/video/service/IDownloadRecordingTaskService.java b/src/main/java/com/gbg/activate/video/service/IDownloadRecordingTaskService.java
new file mode 100644
index 0000000..bd5433a
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/service/IDownloadRecordingTaskService.java
@@ -0,0 +1,13 @@
+package com.gbg.activate.video.service;
+
+public interface IDownloadRecordingTaskService {
+ /**
+ * @Title: processPendingTasks
+ * @Description: 处理下载任务
+ * @return void 返回类型
+ * @throws
+ * @author Frank.Wang@gbgplc.com
+ * @date 2025-07-15 03:15:08
+ */
+ void processPendingTasks();
+}
diff --git a/src/main/java/com/gbg/activate/video/service/IDownloadTaskService.java b/src/main/java/com/gbg/activate/video/service/IDownloadTaskService.java
new file mode 100644
index 0000000..59ea8a5
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/service/IDownloadTaskService.java
@@ -0,0 +1,13 @@
+package com.gbg.activate.video.service;
+
+public interface IDownloadTaskService {
+ /**
+ * @Title: processPendingTasks
+ * @Description: 处理下载任务
+ * @return void 返回类型
+ * @throws
+ * @author Frank.Wang@gbgplc.com
+ * @date 2025-07-15 03:15:08
+ */
+ void processPendingTasks();
+}
diff --git a/src/main/java/com/gbg/activate/video/service/IRecordingViewService.java b/src/main/java/com/gbg/activate/video/service/IRecordingViewService.java
new file mode 100644
index 0000000..05edbe7
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/service/IRecordingViewService.java
@@ -0,0 +1,21 @@
+package com.gbg.activate.video.service;
+
+import org.springframework.core.io.Resource;
+
+import java.net.MalformedURLException;
+
+public interface IRecordingViewService {
+
+ /**
+ * @Title: viewFile
+ * @Description: 查看视频文件
+ * @param fileName
+ * @return
+ * @throws MalformedURLException 参数
+ * @return Resource 返回类型
+ * @throws
+ * @author Frank.Wang@gbgplc.com
+ * @date 2025-07-15 05:28:26
+ */
+ Resource viewFile(String fileName) throws MalformedURLException;
+}
diff --git a/src/main/java/com/gbg/activate/video/service/IVideoViewService.java b/src/main/java/com/gbg/activate/video/service/IVideoViewService.java
new file mode 100644
index 0000000..d5265d8
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/service/IVideoViewService.java
@@ -0,0 +1,21 @@
+package com.gbg.activate.video.service;
+
+import java.net.MalformedURLException;
+
+import org.springframework.core.io.Resource;
+
+public interface IVideoViewService {
+
+ /**
+ * @Title: viewFile
+ * @Description: 查看视频文件
+ * @param fileName
+ * @return
+ * @throws MalformedURLException 参数
+ * @return Resource 返回类型
+ * @throws
+ * @author Frank.Wang@gbgplc.com
+ * @date 2025-07-15 05:28:26
+ */
+ Resource viewFile(String fileName) throws MalformedURLException;
+}
diff --git a/src/main/java/com/gbg/activate/video/service/RecordingViewServiceImpl.java b/src/main/java/com/gbg/activate/video/service/RecordingViewServiceImpl.java
new file mode 100644
index 0000000..781c788
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/service/RecordingViewServiceImpl.java
@@ -0,0 +1,24 @@
+package com.gbg.activate.video.service;
+
+import com.gbg.activate.video.config.ImageSdkParams;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.UrlResource;
+import org.springframework.stereotype.Service;
+
+import java.net.MalformedURLException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+@Service
+public class RecordingViewServiceImpl implements IRecordingViewService {
+ @Autowired
+ private ImageSdkParams params;
+
+ @Override
+ public Resource viewFile(String fileName) throws MalformedURLException {
+ Path filePath = Paths.get(params.getFileSavePath()).resolve(fileName).normalize();
+ return new UrlResource(filePath.toUri());
+ }
+
+}
diff --git a/src/main/java/com/gbg/activate/video/service/VideoViewServiceImpl.java b/src/main/java/com/gbg/activate/video/service/VideoViewServiceImpl.java
new file mode 100644
index 0000000..dcc0a7a
--- /dev/null
+++ b/src/main/java/com/gbg/activate/video/service/VideoViewServiceImpl.java
@@ -0,0 +1,25 @@
+package com.gbg.activate.video.service;
+
+import java.net.MalformedURLException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.UrlResource;
+import org.springframework.stereotype.Service;
+
+import com.gbg.activate.video.config.ImageSdkParams;
+
+@Service
+public class VideoViewServiceImpl implements IVideoViewService {
+ @Autowired
+ private ImageSdkParams params;
+
+ @Override
+ public Resource viewFile(String fileName) throws MalformedURLException {
+ Path filePath = Paths.get(params.getFileSavePath()).resolve(fileName).normalize();
+ return new UrlResource(filePath.toUri());
+ }
+
+}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
new file mode 100644
index 0000000..b80a9b5
--- /dev/null
+++ b/src/main/resources/application-dev.yml
@@ -0,0 +1,58 @@
+server.address: 127.0.0.1
+server.port: 8090
+spring.datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
+ url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ActivateCMBC;encrypt=false;SelectMethod=cursor;
+ username: ActivateSysAdm
+ # Initialization size, minimum, maximum
+ initial-size: 5
+ min-idle: 5
+ max-active: 20
+ # Configuration to get the connection waiting timeout time
+ max-wait: 60000
+ # How often is the configuration interval detected to detect idle connections that need to be closed in milliseconds?
+ time-between-eviction-runs-millis: 60000
+ # Configure the minimum lifetime of a connection in the pool in milliseconds
+ min-evictable-idle-time-millis: 300000
+ #Detecting whether the connection is valid sql
+ validation-query: SELECT 'x'
+ validation-query-timeout: 60000
+ test-while-idle: false
+ test-on-borrow: false
+ test-on-return: false
+ # Recommended closure under PSCache Mysql
+ pool-prepared-statements: false
+ max-pool-prepared-statement-per-connection-size: -1
+ password-callback-class-name: com.gbg.activate.video.config.GBGDruidPasswordCallback
+ connect-properties.password: ZGVjdGVjaA==
+logging.config: classpath:logback-spring.xml
+spring.quartz:
+ job-store-type: jdbc
+ auto-startup: true
+ overwrite-existing-jobs: true
+ startup-delay: 2
+ properties.org.quartz:
+ jobStore:
+ isClustered: true
+ clusterCheckinInterval: 20000
+ acquireTriggersWithinLock: true
+ scheduler:
+ instanceId: AUTO
+ instanceName: DownloadScheduler
+ threadPool:
+ threadCount: 10
+ threadPriority: 5
+download.cron: 0 */5 * * * ?
+clear-expired.cron: 0 */5 * * * ?
+clean-audio.cron: 0 0 3 * * ?
+image-sdk:
+ icmsF5Ip: icmsapp.icms.uat.cmbc.cn
+ wmNo: 2
+ cTime: 180
+ rTime: 180
+ sysNo: 887_CM5
+ fileSavePath: /data/videos
+ validDays: 30
+ sysNo1: FXV_T73
+ fileSavePath1: D:\tupian\downloadBigImage
diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml
new file mode 100644
index 0000000..e0e07dc
--- /dev/null
+++ b/src/main/resources/application-prod.yml
@@ -0,0 +1,58 @@
+server.address: 127.0.0.1
+server.port: 8090
+spring.datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
+ url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ActivateCMBC;encrypt=false;SelectMethod=cursor;
+ username: ActivateSysAdm
+ # Initialization size, minimum, maximum
+ initial-size: 5
+ min-idle: 5
+ max-active: 20
+ # Configuration to get the connection waiting timeout time
+ max-wait: 60000
+ # How often is the configuration interval detected to detect idle connections that need to be closed in milliseconds?
+ time-between-eviction-runs-millis: 60000
+ # Configure the minimum lifetime of a connection in the pool in milliseconds
+ min-evictable-idle-time-millis: 300000
+ #Detecting whether the connection is valid sql
+ validation-query: SELECT 'x'
+ validation-query-timeout: 60000
+ test-while-idle: false
+ test-on-borrow: false
+ test-on-return: false
+ # Recommended closure under PSCache Mysql
+ pool-prepared-statements: false
+ max-pool-prepared-statement-per-connection-size: -1
+ password-callback-class-name: com.gbg.activate.video.config.GBGDruidPasswordCallback
+ connect-properties.password: ZGVjdGVjaA==
+logging.config: classpath:logback-spring.xml
+spring.quartz:
+ job-store-type: jdbc
+ auto-startup: true
+ overwrite-existing-jobs: true
+ startup-delay: 2
+ properties.org.quartz:
+ jobStore:
+ isClustered: true
+ clusterCheckinInterval: 20000
+ acquireTriggersWithinLock: true
+ scheduler:
+ instanceId: AUTO
+ instanceName: DownloadScheduler
+ threadPool:
+ threadCount: 10
+ threadPriority: 5
+download.cron: 0 */5 * * * ?
+clear-expired.cron: 0 */5 * * * ?
+clean-audio.cron: 0 0 3 * * ?
+image-sdk:
+ icmsF5Ip: icmsapp.icms.uat.cmbc.cn
+ wmNo: 2
+ cTime: 180
+ rTime: 180
+ sysNo: 887_CM5
+ fileSavePath: /data/videos
+ validDays: 30
+ sysNo1: FXV_T73
+ fileSavePath1: \data\navs
diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml
new file mode 100644
index 0000000..ecad1de
--- /dev/null
+++ b/src/main/resources/application-test.yml
@@ -0,0 +1,59 @@
+server.address: 127.0.0.1
+server.port: 8090
+record.server.port: 9080
+spring.datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
+ url: jdbc:sqlserver://195.203.6.137:1433;DatabaseName=ActivateCMBC;encrypt=false;SelectMethod=cursor;
+ username: ActivateSysAdm
+ # Initialization size, minimum, maximum
+ initial-size: 5
+ min-idle: 5
+ max-active: 20
+ # Configuration to get the connection waiting timeout time
+ max-wait: 60000
+ # How often is the configuration interval detected to detect idle connections that need to be closed in milliseconds?
+ time-between-eviction-runs-millis: 60000
+ # Configure the minimum lifetime of a connection in the pool in milliseconds
+ min-evictable-idle-time-millis: 300000
+ #Detecting whether the connection is valid sql
+ validation-query: SELECT 'x'
+ validation-query-timeout: 60000
+ test-while-idle: false
+ test-on-borrow: false
+ test-on-return: false
+ # Recommended closure under PSCache Mysql
+ pool-prepared-statements: false
+ max-pool-prepared-statement-per-connection-size: -1
+ password-callback-class-name: com.gbg.activate.video.config.GBGDruidPasswordCallback
+ connect-properties.password: QWN0QDE3MjEzIQ==
+logging.config: classpath:logback-spring.xml
+spring.quartz:
+ job-store-type: jdbc
+ auto-startup: true
+ overwrite-existing-jobs: true
+ startup-delay: 2
+ properties.org.quartz:
+ jobStore:
+ isClustered: true
+ clusterCheckinInterval: 20000
+ acquireTriggersWithinLock: true
+ scheduler:
+ instanceId: AUTO
+ instanceName: DownloadScheduler
+ threadPool:
+ threadCount: 10
+ threadPriority: 5
+download.cron: 0 */5 * * * ?
+clear-expired.cron: 0 */5 * * * ?
+clean-audio.cron: 0 0 3 * * ?
+image-sdk:
+ icmsF5Ip: icmsapp.icms.uat.cmbc.cn
+ wmNo: 2
+ cTime: 180
+ rTime: 180
+ sysNo: 887_CM5
+ fileSavePath: /data/videos
+ validDays: 30
+ sysNo1: FXV_T73
+ fileSavePath1: /var/data/nas
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
new file mode 100644
index 0000000..ad23367
--- /dev/null
+++ b/src/main/resources/application.yml
@@ -0,0 +1 @@
+spring.profiles.active: test
diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml
new file mode 100644
index 0000000..585b083
--- /dev/null
+++ b/src/main/resources/logback-spring.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${log.pattern}
+
+
+
+
+ ${log.filePath}/activate-video-service.log
+
+
+ ${log.filePath}/activate-video-service.%d{yyyy-MM-dd}.log.gz
+
+
+ 30
+
+
+ ${log.pattern}
+ UTF-8
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/sg/sg_config.properties b/src/main/resources/sg/sg_config.properties
new file mode 100644
index 0000000..e2268ff
--- /dev/null
+++ b/src/main/resources/sg/sg_config.properties
@@ -0,0 +1,5 @@
+sg.zk-iplist=zksgc.dev.cmbc.cn:2181
+sg.serviceUnitCode=CCACTIVATE-PRD-ONE
+sg.rootPath=/dayugvm/uat/sg
+sg.pushLog=N
+sg.obsUpdateFlag=N
\ No newline at end of file
diff --git a/src/test/java/com/gbg/activate/video/test/ActivateVideoApplicationTests.java b/src/test/java/com/gbg/activate/video/test/ActivateVideoApplicationTests.java
new file mode 100644
index 0000000..18ff9b4
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/ActivateVideoApplicationTests.java
@@ -0,0 +1,13 @@
+package com.gbg.activate.video.test;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class ActivateVideoApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/src/test/java/com/gbg/activate/video/test/config/DownloadSchedulerConfigTest.java b/src/test/java/com/gbg/activate/video/test/config/DownloadSchedulerConfigTest.java
new file mode 100644
index 0000000..dc9e0c6
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/config/DownloadSchedulerConfigTest.java
@@ -0,0 +1,106 @@
+package com.gbg.activate.video.test.config;
+
+import com.gbg.activate.video.config.DownloadSchedulerConfig;
+import com.gbg.activate.video.job.AudioFileCleanupJob;
+import com.gbg.activate.video.job.ClearExpiredFileJob;
+import com.gbg.activate.video.job.RecordingDownloadJob;
+import com.gbg.activate.video.job.VideoDownloadJob;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.quartz.JobDetail;
+import org.quartz.Trigger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+@TestPropertySource(properties = {
+ "download.cron=0 */5 * * * ?",
+ "clear-expired.cron=0 */10 * * * ?",
+ "clean-audio.cron=0 0 3 * * ?"
+})
+public class DownloadSchedulerConfigTest {
+
+ @Autowired
+ private DownloadSchedulerConfig downloadSchedulerConfig;
+
+ @Test
+ public void testConfigBeanCreation() {
+ Assertions.assertNotNull(downloadSchedulerConfig);
+ }
+
+ @Test
+ public void testDownloadJobDetailCreation() {
+ JobDetail jobDetail = downloadSchedulerConfig.downloadJobDetail();
+ Assertions.assertNotNull(jobDetail);
+ Assertions.assertEquals("VideoDownloadJob", jobDetail.getKey().getName());
+ Assertions.assertEquals("VideoGroup", jobDetail.getKey().getGroup());
+ Assertions.assertTrue(jobDetail.isDurable());
+ Assertions.assertEquals(VideoDownloadJob.class, jobDetail.getJobClass());
+ }
+
+ @Test
+ public void testDownloadJobTriggerCreation() {
+ Trigger trigger = downloadSchedulerConfig.downloadJobTrigger();
+ Assertions.assertNotNull(trigger);
+ Assertions.assertEquals("VideoDownloadTrigger", trigger.getKey().getName());
+ Assertions.assertEquals("VideoGroup", trigger.getKey().getGroup());
+ }
+
+ @Test
+ public void testClearExpiredFileJobDetailCreation() {
+ JobDetail jobDetail = downloadSchedulerConfig.clearExpiredFileJobDetail();
+ Assertions.assertNotNull(jobDetail);
+ Assertions.assertEquals("ClearExpiredFileJob", jobDetail.getKey().getName());
+ Assertions.assertEquals("VideoGroup", jobDetail.getKey().getGroup());
+ Assertions.assertTrue(jobDetail.isDurable());
+ Assertions.assertEquals(ClearExpiredFileJob.class, jobDetail.getJobClass());
+ }
+
+ @Test
+ public void testClearExpiredFileJobTriggerCreation() {
+ Trigger trigger = downloadSchedulerConfig.clearExpiredFileJobTrigger();
+ Assertions.assertNotNull(trigger);
+ Assertions.assertEquals("ClearExpiredFileTrigger", trigger.getKey().getName());
+ Assertions.assertEquals("VideoGroup", trigger.getKey().getGroup());
+ }
+
+ @Test
+ public void testDownloadRecordingJobDetailCreation() {
+ JobDetail jobDetail = downloadSchedulerConfig.downloadRecordingJobDetail();
+ Assertions.assertNotNull(jobDetail);
+ Assertions.assertEquals("downloadRecordingJobDetail", jobDetail.getKey().getName());
+ Assertions.assertEquals("VideoGroup", jobDetail.getKey().getGroup());
+ Assertions.assertTrue(jobDetail.isDurable());
+ Assertions.assertEquals(RecordingDownloadJob.class, jobDetail.getJobClass());
+ }
+
+ @Test
+ public void testDownloadRecordingJobTriggerCreation() {
+ Trigger trigger = downloadSchedulerConfig.downloadJobRecordingTrigger();
+ Assertions.assertNotNull(trigger);
+ Assertions.assertEquals("downloadJobRecordingTrigger", trigger.getKey().getName());
+ Assertions.assertEquals("VideoGroup", trigger.getKey().getGroup());
+ }
+
+ @Test
+ public void testCleanAudioJobDetailCreation() {
+ JobDetail jobDetail = downloadSchedulerConfig.cleanAudioJobDetail();
+ Assertions.assertNotNull(jobDetail);
+ Assertions.assertEquals("cleanAudioJobDetail", jobDetail.getKey().getName());
+ Assertions.assertEquals("VideoGroup", jobDetail.getKey().getGroup());
+ Assertions.assertTrue(jobDetail.isDurable());
+ Assertions.assertEquals(AudioFileCleanupJob.class, jobDetail.getJobClass());
+ }
+
+ @Test
+ public void testCleanupAudioTriggerCreation() {
+ Trigger trigger = downloadSchedulerConfig.cleanupAudioTrigger();
+ Assertions.assertNotNull(trigger);
+ Assertions.assertEquals("cleanupAudioTrigger", trigger.getKey().getName());
+ Assertions.assertEquals("VideoGroup", trigger.getKey().getGroup());
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/config/DruidConfigTest.java b/src/test/java/com/gbg/activate/video/test/config/DruidConfigTest.java
new file mode 100644
index 0000000..0cacf11
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/config/DruidConfigTest.java
@@ -0,0 +1,40 @@
+package com.gbg.activate.video.test.config;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.gbg.activate.video.config.DruidConfig;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import javax.sql.DataSource;
+
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+public class DruidConfigTest {
+
+ @Autowired
+ private DruidConfig druidConfig;
+
+ @Autowired
+ private DataSource dataSource;
+
+ @Test
+ public void testConfigBeanCreation() {
+ Assertions.assertNotNull(druidConfig);
+ }
+
+ @Test
+ public void testDruidDataSourceCreation() {
+ Assertions.assertNotNull(dataSource);
+ Assertions.assertTrue(dataSource instanceof DruidDataSource);
+ }
+
+ @Test
+ public void testDruidDataSourceType() {
+ DruidDataSource druidDataSource = (DruidDataSource) dataSource;
+ Assertions.assertNotNull(druidDataSource);
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/config/GBGBase64UtilsTest.java b/src/test/java/com/gbg/activate/video/test/config/GBGBase64UtilsTest.java
new file mode 100644
index 0000000..938f4dc
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/config/GBGBase64UtilsTest.java
@@ -0,0 +1,75 @@
+package com.gbg.activate.video.test.config;
+
+import com.gbg.activate.video.config.GBGBase64Utils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class GBGBase64UtilsTest {
+
+ @Test
+ public void testEncodeWithNormalString() {
+ String original = "Hello World";
+ String encoded = GBGBase64Utils.encode(original);
+ Assertions.assertNotNull(encoded);
+ Assertions.assertEquals("SGVsbG8gV29ybGQ=", encoded);
+ }
+
+ @Test
+ public void testDecodeWithNormalString() {
+ String encoded = "SGVsbG8gV29ybGQ=";
+ String decoded = GBGBase64Utils.decode(encoded);
+ Assertions.assertNotNull(decoded);
+ Assertions.assertEquals("Hello World", decoded);
+ }
+
+ @Test
+ public void testEncodeAndDecode() {
+ String original = "Test String 123!@#";
+ String encoded = GBGBase64Utils.encode(original);
+ String decoded = GBGBase64Utils.decode(encoded);
+ Assertions.assertEquals(original, decoded);
+ }
+
+ @Test
+ public void testEncodeWithEmptyString() {
+ String original = "";
+ String encoded = GBGBase64Utils.encode(original);
+ Assertions.assertNotNull(encoded);
+ Assertions.assertEquals("", encoded);
+ }
+
+ @Test
+ public void testDecodeWithEmptyString() {
+ String encoded = "";
+ String decoded = GBGBase64Utils.decode(encoded);
+ Assertions.assertNotNull(decoded);
+ Assertions.assertEquals("", decoded);
+ }
+
+ @Test
+ public void testEncodeWithChinese() {
+ String original = "测试中文";
+ String encoded = GBGBase64Utils.encode(original);
+ Assertions.assertNotNull(encoded);
+ String decoded = GBGBase64Utils.decode(encoded);
+ Assertions.assertEquals(original, decoded);
+ }
+
+ @Test
+ public void testEncodeWithSpecialCharacters() {
+ String original = "!@#$%^&*()_+-=[]{}|;':\",./<>?";
+ String encoded = GBGBase64Utils.encode(original);
+ Assertions.assertNotNull(encoded);
+ String decoded = GBGBase64Utils.decode(encoded);
+ Assertions.assertEquals(original, decoded);
+ }
+
+ @Test
+ public void testEncodeWithNumbers() {
+ String original = "1234567890";
+ String encoded = GBGBase64Utils.encode(original);
+ Assertions.assertNotNull(encoded);
+ String decoded = GBGBase64Utils.decode(encoded);
+ Assertions.assertEquals(original, decoded);
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/config/GBGDruidPasswordCallbackTest.java b/src/test/java/com/gbg/activate/video/test/config/GBGDruidPasswordCallbackTest.java
new file mode 100644
index 0000000..7fd7e19
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/config/GBGDruidPasswordCallbackTest.java
@@ -0,0 +1,90 @@
+package com.gbg.activate.video.test.config;
+
+import com.gbg.activate.video.config.GBGDruidPasswordCallback;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.Properties;
+
+public class GBGDruidPasswordCallbackTest {
+
+ @Test
+ public void testSetPropertiesWithValidEncodedPassword() {
+ GBGDruidPasswordCallback callback = new GBGDruidPasswordCallback();
+ Properties properties = new Properties();
+ String originalPassword = "Test@123!";
+ String encodedPassword = java.util.Base64.getEncoder().encodeToString(originalPassword.getBytes());
+ properties.setProperty("password", encodedPassword);
+
+ callback.setProperties(properties);
+
+ char[] password = callback.getPassword();
+ Assertions.assertNotNull(password);
+ Assertions.assertEquals(originalPassword, new String(password));
+ }
+
+ @Test
+ public void testSetPropertiesWithEmptyPassword() {
+ GBGDruidPasswordCallback callback = new GBGDruidPasswordCallback();
+ Properties properties = new Properties();
+ properties.setProperty("password", "");
+
+ callback.setProperties(properties);
+
+ char[] password = callback.getPassword();
+ Assertions.assertNull(password);
+ }
+
+ @Test
+ public void testSetPropertiesWithNullPassword() {
+ GBGDruidPasswordCallback callback = new GBGDruidPasswordCallback();
+ Properties properties = new Properties();
+
+ callback.setProperties(properties);
+
+ char[] password = callback.getPassword();
+ Assertions.assertNull(password);
+ }
+
+ @Test
+ public void testSetPropertiesWithInvalidEncodedPassword() {
+ GBGDruidPasswordCallback callback = new GBGDruidPasswordCallback();
+ Properties properties = new Properties();
+ properties.setProperty("password", "!!!invalid-base64!!!");
+
+ callback.setProperties(properties);
+
+ char[] password = callback.getPassword();
+ Assertions.assertNotNull(password);
+ }
+
+ @Test
+ public void testSetPropertiesWithChinesePassword() {
+ GBGDruidPasswordCallback callback = new GBGDruidPasswordCallback();
+ Properties properties = new Properties();
+ String originalPassword = "测试密码123";
+ String encodedPassword = java.util.Base64.getEncoder().encodeToString(originalPassword.getBytes());
+ properties.setProperty("password", encodedPassword);
+
+ callback.setProperties(properties);
+
+ char[] password = callback.getPassword();
+ Assertions.assertNotNull(password);
+ Assertions.assertEquals(originalPassword, new String(password));
+ }
+
+ @Test
+ public void testSetPropertiesWithSpecialCharacters() {
+ GBGDruidPasswordCallback callback = new GBGDruidPasswordCallback();
+ Properties properties = new Properties();
+ String originalPassword = "!@#$%^&*()_+-=";
+ String encodedPassword = java.util.Base64.getEncoder().encodeToString(originalPassword.getBytes());
+ properties.setProperty("password", encodedPassword);
+
+ callback.setProperties(properties);
+
+ char[] password = callback.getPassword();
+ Assertions.assertNotNull(password);
+ Assertions.assertEquals(originalPassword, new String(password));
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/config/ImageSdkConfigTest.java b/src/test/java/com/gbg/activate/video/test/config/ImageSdkConfigTest.java
new file mode 100644
index 0000000..073f576
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/config/ImageSdkConfigTest.java
@@ -0,0 +1,49 @@
+package com.gbg.activate.video.test.config;
+
+import com.gbg.activate.video.config.ImageSdkConfig;
+import com.gbg.activate.video.config.ImageSdkParams;
+import com.icms.sdk.inter.ImageSdkInter;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+public class ImageSdkConfigTest {
+
+ @Autowired
+ private ImageSdkConfig imageSdkConfig;
+
+ @Autowired
+ private ImageSdkParams imageSdkParams;
+
+ @Test
+ public void testConfigBeanCreation() {
+ Assertions.assertNotNull(imageSdkConfig);
+ }
+
+ @Test
+ public void testImageSdkParamsBeanCreation() {
+ Assertions.assertNotNull(imageSdkParams);
+ }
+
+ @Test
+ public void testInitImageSdk() {
+ ImageSdkInter imageService = imageSdkConfig.initImageSdk();
+ Assertions.assertNotNull(imageService);
+ }
+
+ @Test
+ public void testImageSdkParamsProperties() {
+ Assertions.assertNotNull(imageSdkParams.getIcmsF5Ip());
+ Assertions.assertNotNull(imageSdkParams.getWmNo());
+ Assertions.assertNotNull(imageSdkParams.getcTime());
+ Assertions.assertNotNull(imageSdkParams.getrTime());
+ Assertions.assertNotNull(imageSdkParams.getSysNo());
+ Assertions.assertNotNull(imageSdkParams.getFileSavePath());
+ Assertions.assertNotNull(imageSdkParams.getValidDays());
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/config/ImageSdkParamsTest.java b/src/test/java/com/gbg/activate/video/test/config/ImageSdkParamsTest.java
new file mode 100644
index 0000000..3f23a11
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/config/ImageSdkParamsTest.java
@@ -0,0 +1,98 @@
+package com.gbg.activate.video.test.config;
+
+import com.gbg.activate.video.config.ImageSdkParams;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+public class ImageSdkParamsTest {
+
+ @Autowired
+ private ImageSdkParams imageSdkParams;
+
+ @Test
+ public void testBeanCreation() {
+ Assertions.assertNotNull(imageSdkParams);
+ }
+
+ @Test
+ public void testGetAndSetIcmsF5Ip() {
+ String value = "test.icms.com";
+ imageSdkParams.setIcmsF5Ip(value);
+ Assertions.assertEquals(value, imageSdkParams.getIcmsF5Ip());
+ }
+
+ @Test
+ public void testGetAndSetWmNo() {
+ String value = "1";
+ imageSdkParams.setWmNo(value);
+ Assertions.assertEquals(value, imageSdkParams.getWmNo());
+ }
+
+ @Test
+ public void testGetAndSetCTime() {
+ String value = "180";
+ imageSdkParams.setcTime(value);
+ Assertions.assertEquals(value, imageSdkParams.getcTime());
+ }
+
+ @Test
+ public void testGetAndSetRTime() {
+ String value = "180";
+ imageSdkParams.setrTime(value);
+ Assertions.assertEquals(value, imageSdkParams.getrTime());
+ }
+
+ @Test
+ public void testGetAndSetSysNo() {
+ String value = "TEST_SYS";
+ imageSdkParams.setSysNo(value);
+ Assertions.assertEquals(value, imageSdkParams.getSysNo());
+ }
+
+ @Test
+ public void testGetAndSetFileSavePath() {
+ String value = "/test/path";
+ imageSdkParams.setFileSavePath(value);
+ Assertions.assertEquals(value, imageSdkParams.getFileSavePath());
+ }
+
+ @Test
+ public void testGetAndSetValidDays() {
+ Integer value = 30;
+ imageSdkParams.setValidDays(value);
+ Assertions.assertEquals(value, imageSdkParams.getValidDays());
+ }
+
+ @Test
+ public void testGetAndSetSysNo1() {
+ String value = "TEST_SYS1";
+ imageSdkParams.setSysNo1(value);
+ Assertions.assertEquals(value, imageSdkParams.getSysNo1());
+ }
+
+ @Test
+ public void testGetAndSetFileSavePath1() {
+ String value = "/test/path1";
+ imageSdkParams.setFileSavePath1(value);
+ Assertions.assertEquals(value, imageSdkParams.getFileSavePath1());
+ }
+
+ @Test
+ public void testConfigurationPropertiesLoaded() {
+ Assertions.assertNotNull(imageSdkParams.getIcmsF5Ip());
+ Assertions.assertNotNull(imageSdkParams.getWmNo());
+ Assertions.assertNotNull(imageSdkParams.getcTime());
+ Assertions.assertNotNull(imageSdkParams.getrTime());
+ Assertions.assertNotNull(imageSdkParams.getSysNo());
+ Assertions.assertNotNull(imageSdkParams.getFileSavePath());
+ Assertions.assertNotNull(imageSdkParams.getValidDays());
+ Assertions.assertNotNull(imageSdkParams.getSysNo1());
+ Assertions.assertNotNull(imageSdkParams.getFileSavePath1());
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/constant/DownloadStatusTest.java b/src/test/java/com/gbg/activate/video/test/constant/DownloadStatusTest.java
new file mode 100644
index 0000000..1aeb54c
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/constant/DownloadStatusTest.java
@@ -0,0 +1,33 @@
+package com.gbg.activate.video.test.constant;
+
+import com.gbg.activate.video.constant.DownloadStatus;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class DownloadStatusTest {
+
+ @Test
+ public void testAllConstants() {
+ Assertions.assertNotNull(DownloadStatus.PENDING);
+ Assertions.assertEquals("PENDING", DownloadStatus.PENDING);
+
+ Assertions.assertNotNull(DownloadStatus.DOWNLOADING);
+ Assertions.assertEquals("DOWNLOADING", DownloadStatus.DOWNLOADING);
+
+ Assertions.assertNotNull(DownloadStatus.COMPLETED);
+ Assertions.assertEquals("COMPLETED", DownloadStatus.COMPLETED);
+
+ Assertions.assertNotNull(DownloadStatus.FAILED);
+ Assertions.assertEquals("FAILED", DownloadStatus.FAILED);
+ }
+
+ @Test
+ public void testConstantsAreDifferent() {
+ Assertions.assertNotEquals(DownloadStatus.PENDING, DownloadStatus.DOWNLOADING);
+ Assertions.assertNotEquals(DownloadStatus.PENDING, DownloadStatus.COMPLETED);
+ Assertions.assertNotEquals(DownloadStatus.PENDING, DownloadStatus.FAILED);
+ Assertions.assertNotEquals(DownloadStatus.DOWNLOADING, DownloadStatus.COMPLETED);
+ Assertions.assertNotEquals(DownloadStatus.DOWNLOADING, DownloadStatus.FAILED);
+ Assertions.assertNotEquals(DownloadStatus.COMPLETED, DownloadStatus.FAILED);
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/controller/RecordingViewControllerTest.java b/src/test/java/com/gbg/activate/video/test/controller/RecordingViewControllerTest.java
new file mode 100644
index 0000000..8df3941
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/controller/RecordingViewControllerTest.java
@@ -0,0 +1,88 @@
+package com.gbg.activate.video.test.controller;
+
+import com.gbg.activate.video.controller.RecordingViewController;
+import com.gbg.activate.video.service.IRecordingViewService;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.springframework.core.io.Resource;
+import org.springframework.http.ResponseEntity;
+
+import java.net.MalformedURLException;
+
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.*;
+
+public class RecordingViewControllerTest {
+
+ private RecordingViewController controller;
+ private IRecordingViewService recordingViewService;
+
+ @BeforeEach
+ public void setUp() {
+ recordingViewService = mock(IRecordingViewService.class);
+ controller = new RecordingViewController();
+ // 通过反射注入 mock 对象
+ try {
+ java.lang.reflect.Field field = RecordingViewController.class.getDeclaredField("recordingViewService");
+ field.setAccessible(true);
+ field.set(controller, recordingViewService);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void testViewFileSuccess() throws MalformedURLException {
+ Resource resource = mock(Resource.class);
+ when(resource.exists()).thenReturn(true);
+ when(resource.isReadable()).thenReturn(true);
+ when(resource.getFilename()).thenReturn("test.mp4");
+ when(recordingViewService.viewFile(anyString())).thenReturn(resource);
+
+ ResponseEntity response = controller.viewFile("test.mp4");
+
+ Assertions.assertNotNull(response);
+ Assertions.assertEquals(200, response.getStatusCodeValue());
+ verify(recordingViewService, times(1)).viewFile("test.mp4");
+ }
+
+ @Test
+ public void testViewFileNotFoundWhenResourceNotExists() throws MalformedURLException {
+ Resource resource = mock(Resource.class);
+ when(resource.exists()).thenReturn(false);
+ when(recordingViewService.viewFile(anyString())).thenReturn(resource);
+
+ ResponseEntity response = controller.viewFile("nonexistent.mp4");
+
+ Assertions.assertNotNull(response);
+ Assertions.assertEquals(404, response.getStatusCodeValue());
+ verify(recordingViewService, times(1)).viewFile("nonexistent.mp4");
+ }
+
+ @Test
+ public void testViewFileNotFoundWhenResourceNotReadable() throws MalformedURLException {
+ Resource resource = mock(Resource.class);
+ when(resource.exists()).thenReturn(true);
+ when(resource.isReadable()).thenReturn(false);
+ when(recordingViewService.viewFile(anyString())).thenReturn(resource);
+
+ ResponseEntity response = controller.viewFile("unreadable.mp4");
+
+ Assertions.assertNotNull(response);
+ Assertions.assertEquals(404, response.getStatusCodeValue());
+ verify(recordingViewService, times(1)).viewFile("unreadable.mp4");
+ }
+
+ @Test
+ public void testViewFileNotFoundOnMalformedURLException() throws MalformedURLException {
+ when(recordingViewService.viewFile(anyString())).thenThrow(new MalformedURLException("Invalid URL"));
+
+ ResponseEntity response = controller.viewFile("invalid.mp4");
+
+ Assertions.assertNotNull(response);
+ Assertions.assertEquals(404, response.getStatusCodeValue());
+ verify(recordingViewService, times(1)).viewFile("invalid.mp4");
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/controller/VideoViewControllerTest.java b/src/test/java/com/gbg/activate/video/test/controller/VideoViewControllerTest.java
new file mode 100644
index 0000000..e93097c
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/controller/VideoViewControllerTest.java
@@ -0,0 +1,87 @@
+package com.gbg.activate.video.test.controller;
+
+import com.gbg.activate.video.controller.VideoViewController;
+import com.gbg.activate.video.service.IVideoViewService;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.core.io.Resource;
+import org.springframework.http.ResponseEntity;
+
+import java.net.MalformedURLException;
+
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.*;
+
+public class VideoViewControllerTest {
+
+ private VideoViewController controller;
+ private IVideoViewService videoViewService;
+
+ @BeforeEach
+ public void setUp() {
+ videoViewService = mock(IVideoViewService.class);
+ controller = new VideoViewController();
+ // 通过反射注入 mock 对象
+ try {
+ java.lang.reflect.Field field = VideoViewController.class.getDeclaredField("videoViewService");
+ field.setAccessible(true);
+ field.set(controller, videoViewService);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void testViewFileSuccess() throws MalformedURLException {
+ Resource resource = mock(Resource.class);
+ when(resource.exists()).thenReturn(true);
+ when(resource.isReadable()).thenReturn(true);
+ when(resource.getFilename()).thenReturn("test.mp4");
+ when(videoViewService.viewFile(anyString())).thenReturn(resource);
+
+ ResponseEntity response = controller.viewFile("test.mp4");
+
+ Assertions.assertNotNull(response);
+ Assertions.assertEquals(200, response.getStatusCodeValue());
+ verify(videoViewService, times(1)).viewFile("test.mp4");
+ }
+
+ @Test
+ public void testViewFileNotFoundWhenResourceNotExists() throws MalformedURLException {
+ Resource resource = mock(Resource.class);
+ when(resource.exists()).thenReturn(false);
+ when(videoViewService.viewFile(anyString())).thenReturn(resource);
+
+ ResponseEntity response = controller.viewFile("nonexistent.mp4");
+
+ Assertions.assertNotNull(response);
+ Assertions.assertEquals(404, response.getStatusCodeValue());
+ verify(videoViewService, times(1)).viewFile("nonexistent.mp4");
+ }
+
+ @Test
+ public void testViewFileNotFoundWhenResourceNotReadable() throws MalformedURLException {
+ Resource resource = mock(Resource.class);
+ when(resource.exists()).thenReturn(true);
+ when(resource.isReadable()).thenReturn(false);
+ when(videoViewService.viewFile(anyString())).thenReturn(resource);
+
+ ResponseEntity response = controller.viewFile("unreadable.mp4");
+
+ Assertions.assertNotNull(response);
+ Assertions.assertEquals(404, response.getStatusCodeValue());
+ verify(videoViewService, times(1)).viewFile("unreadable.mp4");
+ }
+
+ @Test
+ public void testViewFileNotFoundOnMalformedURLException() throws MalformedURLException {
+ when(videoViewService.viewFile(anyString())).thenThrow(new MalformedURLException("Invalid URL"));
+
+ ResponseEntity response = controller.viewFile("invalid.mp4");
+
+ Assertions.assertNotNull(response);
+ Assertions.assertEquals(404, response.getStatusCodeValue());
+ verify(videoViewService, times(1)).viewFile("invalid.mp4");
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/entity/RecordingDownloadDOTest.java b/src/test/java/com/gbg/activate/video/test/entity/RecordingDownloadDOTest.java
new file mode 100644
index 0000000..325135c
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/entity/RecordingDownloadDOTest.java
@@ -0,0 +1,171 @@
+package com.gbg.activate.video.test.entity;
+
+import com.gbg.activate.video.entity.RecordingDownloadDO;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.Date;
+
+public class RecordingDownloadDOTest {
+
+ @Test
+ public void testGettersAndSetters() {
+ RecordingDownloadDO record = new RecordingDownloadDO();
+ Date now = new Date();
+
+ record.setApplicationNumber("APP001");
+ record.setCallId("CALL001");
+ record.setImageId("IMG001");
+ record.setImageName("test.mp4");
+ record.setImageType("mp4");
+ record.setImageSize("1024");
+ record.setImageUrl("http://example.com/test.mp4");
+ record.setCreateTime("2025-01-01");
+ record.setDownloadTime(now);
+
+ Assertions.assertEquals("APP001", record.getApplicationNumber());
+ Assertions.assertEquals("CALL001", record.getCallId());
+ Assertions.assertEquals("IMG001", record.getImageId());
+ Assertions.assertEquals("test.mp4", record.getImageName());
+ Assertions.assertEquals("mp4", record.getImageType());
+ Assertions.assertEquals("1024", record.getImageSize());
+ Assertions.assertEquals("http://example.com/test.mp4", record.getImageUrl());
+ Assertions.assertEquals("2025-01-01", record.getCreateTime());
+ Assertions.assertEquals(now, record.getDownloadTime());
+ }
+
+ @Test
+ public void testSettersWithNullValues() {
+ RecordingDownloadDO record = new RecordingDownloadDO();
+
+ record.setApplicationNumber(null);
+ record.setCallId(null);
+ record.setImageId(null);
+ record.setImageName(null);
+ record.setImageType(null);
+ record.setImageSize(null);
+ record.setImageUrl(null);
+ record.setCreateTime(null);
+ record.setDownloadTime(null);
+
+ Assertions.assertNull(record.getApplicationNumber());
+ Assertions.assertNull(record.getCallId());
+ Assertions.assertNull(record.getImageId());
+ Assertions.assertNull(record.getImageName());
+ Assertions.assertNull(record.getImageType());
+ Assertions.assertNull(record.getImageSize());
+ Assertions.assertNull(record.getImageUrl());
+ Assertions.assertNull(record.getCreateTime());
+ Assertions.assertNull(record.getDownloadTime());
+ }
+
+ @Test
+ public void testSettersWithTrimmedValues() {
+ RecordingDownloadDO record = new RecordingDownloadDO();
+
+ record.setApplicationNumber(" APP001 ");
+ record.setCallId(" CALL001 ");
+ record.setImageId(" IMG001 ");
+ record.setImageName(" test.mp4 ");
+ record.setImageType(" mp4 ");
+ record.setImageSize(" 1024 ");
+ record.setImageUrl(" http://example.com/test.mp4 ");
+ record.setCreateTime(" 2025-01-01 ");
+
+ Assertions.assertEquals("APP001", record.getApplicationNumber());
+ Assertions.assertEquals("CALL001", record.getCallId());
+ Assertions.assertEquals("IMG001", record.getImageId());
+ Assertions.assertEquals("test.mp4", record.getImageName());
+ Assertions.assertEquals("mp4", record.getImageType());
+ Assertions.assertEquals("1024", record.getImageSize());
+ Assertions.assertEquals("http://example.com/test.mp4", record.getImageUrl());
+ Assertions.assertEquals("2025-01-01", record.getCreateTime());
+ }
+
+ @Test
+ public void testEqualsWithSameObject() {
+ RecordingDownloadDO record = new RecordingDownloadDO();
+ record.setApplicationNumber("APP001");
+
+ Assertions.assertTrue(record.equals(record));
+ }
+
+ @Test
+ public void testEqualsWithNull() {
+ RecordingDownloadDO record = new RecordingDownloadDO();
+
+ Assertions.assertFalse(record.equals(null));
+ }
+
+ @Test
+ public void testEqualsWithDifferentClass() {
+ RecordingDownloadDO record = new RecordingDownloadDO();
+
+ Assertions.assertFalse(record.equals("string"));
+ }
+
+ @Test
+ public void testEqualsWithSameValues() {
+ RecordingDownloadDO record1 = new RecordingDownloadDO();
+ record1.setApplicationNumber("APP001");
+ record1.setCallId("CALL001");
+ record1.setImageId("IMG001");
+
+ RecordingDownloadDO record2 = new RecordingDownloadDO();
+ record2.setApplicationNumber("APP001");
+ record2.setCallId("CALL001");
+ record2.setImageId("IMG001");
+
+ Assertions.assertTrue(record1.equals(record2));
+ }
+
+ @Test
+ public void testEqualsWithDifferentValues() {
+ RecordingDownloadDO record1 = new RecordingDownloadDO();
+ record1.setApplicationNumber("APP001");
+
+ RecordingDownloadDO record2 = new RecordingDownloadDO();
+ record2.setApplicationNumber("APP002");
+
+ Assertions.assertFalse(record1.equals(record2));
+ }
+
+ @Test
+ public void testEqualsWithNullFields() {
+ RecordingDownloadDO record1 = new RecordingDownloadDO();
+ RecordingDownloadDO record2 = new RecordingDownloadDO();
+
+ Assertions.assertTrue(record1.equals(record2));
+ }
+
+ @Test
+ public void testHashCode() {
+ RecordingDownloadDO record = new RecordingDownloadDO();
+ record.setApplicationNumber("APP001");
+ record.setCallId("CALL001");
+
+ int hashCode = record.hashCode();
+ Assertions.assertNotEquals(0, hashCode);
+
+ RecordingDownloadDO record2 = new RecordingDownloadDO();
+ record2.setApplicationNumber("APP001");
+ record2.setCallId("CALL001");
+
+ Assertions.assertEquals(record.hashCode(), record2.hashCode());
+ }
+
+ @Test
+ public void testToString() {
+ RecordingDownloadDO record = new RecordingDownloadDO();
+ record.setApplicationNumber("APP001");
+ record.setCallId("CALL001");
+ record.setImageName("test.mp4");
+
+ String result = record.toString();
+ Assertions.assertNotNull(result);
+ Assertions.assertTrue(result.contains("RecordingDownloadDO"));
+ Assertions.assertTrue(result.contains("APP001"));
+ Assertions.assertTrue(result.contains("CALL001"));
+ Assertions.assertTrue(result.contains("test.mp4"));
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/entity/RecordingPendingDownloadQueueDOTest.java b/src/test/java/com/gbg/activate/video/test/entity/RecordingPendingDownloadQueueDOTest.java
new file mode 100644
index 0000000..ec4353b
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/entity/RecordingPendingDownloadQueueDOTest.java
@@ -0,0 +1,174 @@
+package com.gbg.activate.video.test.entity;
+
+import com.gbg.activate.video.entity.RecordingPendingDownloadQueueDO;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.Date;
+
+public class RecordingPendingDownloadQueueDOTest {
+
+ @Test
+ public void testGettersAndSetters() {
+ RecordingPendingDownloadQueueDO queue = new RecordingPendingDownloadQueueDO();
+ Date now = new Date();
+
+ queue.setSerialNumber(1L);
+ queue.setApplicationNumber("APP001");
+ queue.setCallId("CALL001");
+ queue.setImageId("IMG001");
+ queue.setDownloadStatus("PENDING");
+ queue.setEntryTime(now);
+ queue.setInvokeTime(now);
+ queue.setRetryCount(0);
+ queue.setMaxRetry(3);
+ queue.setInvokePriority(1);
+ queue.setErrorMessage("No error");
+
+ Assertions.assertEquals(Long.valueOf(1L), queue.getSerialNumber());
+ Assertions.assertEquals("APP001", queue.getApplicationNumber());
+ Assertions.assertEquals("CALL001", queue.getCallId());
+ Assertions.assertEquals("IMG001", queue.getImageId());
+ Assertions.assertEquals("PENDING", queue.getDownloadStatus());
+ Assertions.assertEquals(now, queue.getEntryTime());
+ Assertions.assertEquals(now, queue.getInvokeTime());
+ Assertions.assertEquals(Integer.valueOf(0), queue.getRetryCount());
+ Assertions.assertEquals(Integer.valueOf(3), queue.getMaxRetry());
+ Assertions.assertEquals(Integer.valueOf(1), queue.getInvokePriority());
+ Assertions.assertEquals("No error", queue.getErrorMessage());
+ }
+
+ @Test
+ public void testSettersWithNullValues() {
+ RecordingPendingDownloadQueueDO queue = new RecordingPendingDownloadQueueDO();
+
+ queue.setSerialNumber(null);
+ queue.setApplicationNumber(null);
+ queue.setCallId(null);
+ queue.setImageId(null);
+ queue.setDownloadStatus(null);
+ queue.setEntryTime(null);
+ queue.setInvokeTime(null);
+ queue.setRetryCount(null);
+ queue.setMaxRetry(null);
+ queue.setInvokePriority(null);
+ queue.setErrorMessage(null);
+
+ Assertions.assertNull(queue.getSerialNumber());
+ Assertions.assertNull(queue.getApplicationNumber());
+ Assertions.assertNull(queue.getCallId());
+ Assertions.assertNull(queue.getImageId());
+ Assertions.assertNull(queue.getDownloadStatus());
+ Assertions.assertNull(queue.getEntryTime());
+ Assertions.assertNull(queue.getInvokeTime());
+ Assertions.assertNull(queue.getRetryCount());
+ Assertions.assertNull(queue.getMaxRetry());
+ Assertions.assertNull(queue.getInvokePriority());
+ Assertions.assertNull(queue.getErrorMessage());
+ }
+
+ @Test
+ public void testSettersWithTrimmedValues() {
+ RecordingPendingDownloadQueueDO queue = new RecordingPendingDownloadQueueDO();
+
+ queue.setApplicationNumber(" APP001 ");
+ queue.setCallId(" CALL001 ");
+ queue.setImageId(" IMG001 ");
+ queue.setDownloadStatus(" PENDING ");
+ queue.setErrorMessage(" Error message ");
+
+ Assertions.assertEquals("APP001", queue.getApplicationNumber());
+ Assertions.assertEquals("CALL001", queue.getCallId());
+ Assertions.assertEquals("IMG001", queue.getImageId());
+ Assertions.assertEquals("PENDING", queue.getDownloadStatus());
+ Assertions.assertEquals("Error message", queue.getErrorMessage());
+ }
+
+ @Test
+ public void testEqualsWithSameObject() {
+ RecordingPendingDownloadQueueDO queue = new RecordingPendingDownloadQueueDO();
+ queue.setSerialNumber(1L);
+
+ Assertions.assertTrue(queue.equals(queue));
+ }
+
+ @Test
+ public void testEqualsWithNull() {
+ RecordingPendingDownloadQueueDO queue = new RecordingPendingDownloadQueueDO();
+
+ Assertions.assertFalse(queue.equals(null));
+ }
+
+ @Test
+ public void testEqualsWithDifferentClass() {
+ RecordingPendingDownloadQueueDO queue = new RecordingPendingDownloadQueueDO();
+
+ Assertions.assertFalse(queue.equals("string"));
+ }
+
+ @Test
+ public void testEqualsWithSameValues() {
+ RecordingPendingDownloadQueueDO queue1 = new RecordingPendingDownloadQueueDO();
+ queue1.setSerialNumber(1L);
+ queue1.setApplicationNumber("APP001");
+ queue1.setCallId("CALL001");
+
+ RecordingPendingDownloadQueueDO queue2 = new RecordingPendingDownloadQueueDO();
+ queue2.setSerialNumber(1L);
+ queue2.setApplicationNumber("APP001");
+ queue2.setCallId("CALL001");
+
+ Assertions.assertTrue(queue1.equals(queue2));
+ }
+
+ @Test
+ public void testEqualsWithDifferentValues() {
+ RecordingPendingDownloadQueueDO queue1 = new RecordingPendingDownloadQueueDO();
+ queue1.setSerialNumber(1L);
+
+ RecordingPendingDownloadQueueDO queue2 = new RecordingPendingDownloadQueueDO();
+ queue2.setSerialNumber(2L);
+
+ Assertions.assertFalse(queue1.equals(queue2));
+ }
+
+ @Test
+ public void testEqualsWithNullFields() {
+ RecordingPendingDownloadQueueDO queue1 = new RecordingPendingDownloadQueueDO();
+ RecordingPendingDownloadQueueDO queue2 = new RecordingPendingDownloadQueueDO();
+
+ Assertions.assertTrue(queue1.equals(queue2));
+ }
+
+ @Test
+ public void testHashCode() {
+ RecordingPendingDownloadQueueDO queue = new RecordingPendingDownloadQueueDO();
+ queue.setSerialNumber(1L);
+ queue.setApplicationNumber("APP001");
+
+ int hashCode = queue.hashCode();
+ Assertions.assertNotEquals(0, hashCode);
+
+ RecordingPendingDownloadQueueDO queue2 = new RecordingPendingDownloadQueueDO();
+ queue2.setSerialNumber(1L);
+ queue2.setApplicationNumber("APP001");
+
+ Assertions.assertEquals(queue.hashCode(), queue2.hashCode());
+ }
+
+ @Test
+ public void testToString() {
+ RecordingPendingDownloadQueueDO queue = new RecordingPendingDownloadQueueDO();
+ queue.setSerialNumber(1L);
+ queue.setApplicationNumber("APP001");
+ queue.setCallId("CALL001");
+ queue.setDownloadStatus("PENDING");
+
+ String result = queue.toString();
+ Assertions.assertNotNull(result);
+ Assertions.assertTrue(result.contains("RecordingPendingDownloadQueueDO"));
+ Assertions.assertTrue(result.contains("APP001"));
+ Assertions.assertTrue(result.contains("CALL001"));
+ Assertions.assertTrue(result.contains("PENDING"));
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/entity/VideoSigningDownloadRecordDOTest.java b/src/test/java/com/gbg/activate/video/test/entity/VideoSigningDownloadRecordDOTest.java
new file mode 100644
index 0000000..3046790
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/entity/VideoSigningDownloadRecordDOTest.java
@@ -0,0 +1,173 @@
+package com.gbg.activate.video.test.entity;
+
+import com.gbg.activate.video.entity.VideoSigningDownloadRecordDO;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.Date;
+
+public class VideoSigningDownloadRecordDOTest {
+
+ @Test
+ public void testGettersAndSetters() {
+ VideoSigningDownloadRecordDO record = new VideoSigningDownloadRecordDO();
+ Date now = new Date();
+
+ record.setApplicationNumber("APP001");
+ record.setImageId("IMG001");
+ record.setImageName("test.mp4");
+ record.setImageType("mp4");
+ record.setImageSize("1024");
+ record.setImageUrl("http://example.com/test.mp4");
+ record.setVideoDuration("00:05:30");
+ record.setCreateTime("2025-01-01");
+ record.setDownloadTime(now);
+
+ Assertions.assertEquals("APP001", record.getApplicationNumber());
+ Assertions.assertEquals("IMG001", record.getImageId());
+ Assertions.assertEquals("test.mp4", record.getImageName());
+ Assertions.assertEquals("mp4", record.getImageType());
+ Assertions.assertEquals("1024", record.getImageSize());
+ Assertions.assertEquals("http://example.com/test.mp4", record.getImageUrl());
+ Assertions.assertEquals("00:05:30", record.getVideoDuration());
+ Assertions.assertEquals("2025-01-01", record.getCreateTime());
+ Assertions.assertEquals(now, record.getDownloadTime());
+ }
+
+ @Test
+ public void testSettersWithNullValues() {
+ VideoSigningDownloadRecordDO record = new VideoSigningDownloadRecordDO();
+
+ record.setApplicationNumber(null);
+ record.setImageId(null);
+ record.setImageName(null);
+ record.setImageType(null);
+ record.setImageSize(null);
+ record.setImageUrl(null);
+ record.setVideoDuration(null);
+ record.setCreateTime(null);
+ record.setDownloadTime(null);
+
+ Assertions.assertNull(record.getApplicationNumber());
+ Assertions.assertNull(record.getImageId());
+ Assertions.assertNull(record.getImageName());
+ Assertions.assertNull(record.getImageType());
+ Assertions.assertNull(record.getImageSize());
+ Assertions.assertNull(record.getImageUrl());
+ Assertions.assertNull(record.getVideoDuration());
+ Assertions.assertNull(record.getCreateTime());
+ Assertions.assertNull(record.getDownloadTime());
+ }
+
+ @Test
+ public void testSettersWithTrimmedValues() {
+ VideoSigningDownloadRecordDO record = new VideoSigningDownloadRecordDO();
+
+ record.setApplicationNumber(" APP001 ");
+ record.setImageId(" IMG001 ");
+ record.setImageName(" test.mp4 ");
+ record.setImageType(" mp4 ");
+ record.setImageSize(" 1024 ");
+ record.setImageUrl(" http://example.com/test.mp4 ");
+ record.setVideoDuration(" 00:05:30 ");
+ record.setCreateTime(" 2025-01-01 ");
+
+ Assertions.assertEquals("APP001", record.getApplicationNumber());
+ Assertions.assertEquals("IMG001", record.getImageId());
+ Assertions.assertEquals("test.mp4", record.getImageName());
+ Assertions.assertEquals("mp4", record.getImageType());
+ Assertions.assertEquals("1024", record.getImageSize());
+ Assertions.assertEquals("http://example.com/test.mp4", record.getImageUrl());
+ Assertions.assertEquals("00:05:30", record.getVideoDuration());
+ Assertions.assertEquals("2025-01-01", record.getCreateTime());
+ }
+
+ @Test
+ public void testEqualsWithSameObject() {
+ VideoSigningDownloadRecordDO record = new VideoSigningDownloadRecordDO();
+ record.setApplicationNumber("APP001");
+
+ Assertions.assertTrue(record.equals(record));
+ }
+
+ @Test
+ public void testEqualsWithNull() {
+ VideoSigningDownloadRecordDO record = new VideoSigningDownloadRecordDO();
+
+ Assertions.assertFalse(record.equals(null));
+ }
+
+ @Test
+ public void testEqualsWithDifferentClass() {
+ VideoSigningDownloadRecordDO record = new VideoSigningDownloadRecordDO();
+
+ Assertions.assertFalse(record.equals("string"));
+ }
+
+ @Test
+ public void testEqualsWithSameValues() {
+ VideoSigningDownloadRecordDO record1 = new VideoSigningDownloadRecordDO();
+ record1.setApplicationNumber("APP001");
+ record1.setImageId("IMG001");
+ record1.setImageName("test.mp4");
+
+ VideoSigningDownloadRecordDO record2 = new VideoSigningDownloadRecordDO();
+ record2.setApplicationNumber("APP001");
+ record2.setImageId("IMG001");
+ record2.setImageName("test.mp4");
+
+ Assertions.assertTrue(record1.equals(record2));
+ }
+
+ @Test
+ public void testEqualsWithDifferentValues() {
+ VideoSigningDownloadRecordDO record1 = new VideoSigningDownloadRecordDO();
+ record1.setApplicationNumber("APP001");
+
+ VideoSigningDownloadRecordDO record2 = new VideoSigningDownloadRecordDO();
+ record2.setApplicationNumber("APP002");
+
+ Assertions.assertFalse(record1.equals(record2));
+ }
+
+ @Test
+ public void testEqualsWithNullFields() {
+ VideoSigningDownloadRecordDO record1 = new VideoSigningDownloadRecordDO();
+ VideoSigningDownloadRecordDO record2 = new VideoSigningDownloadRecordDO();
+
+ Assertions.assertTrue(record1.equals(record2));
+ }
+
+ @Test
+ public void testHashCode() {
+ VideoSigningDownloadRecordDO record = new VideoSigningDownloadRecordDO();
+ record.setApplicationNumber("APP001");
+ record.setImageId("IMG001");
+
+ int hashCode = record.hashCode();
+ Assertions.assertNotEquals(0, hashCode);
+
+ VideoSigningDownloadRecordDO record2 = new VideoSigningDownloadRecordDO();
+ record2.setApplicationNumber("APP001");
+ record2.setImageId("IMG001");
+
+ Assertions.assertEquals(record.hashCode(), record2.hashCode());
+ }
+
+ @Test
+ public void testToString() {
+ VideoSigningDownloadRecordDO record = new VideoSigningDownloadRecordDO();
+ record.setApplicationNumber("APP001");
+ record.setImageId("IMG001");
+ record.setImageName("test.mp4");
+ record.setVideoDuration("00:05:30");
+
+ String result = record.toString();
+ Assertions.assertNotNull(result);
+ Assertions.assertTrue(result.contains("VideoSigningDownloadRecordDO"));
+ Assertions.assertTrue(result.contains("APP001"));
+ Assertions.assertTrue(result.contains("IMG001"));
+ Assertions.assertTrue(result.contains("test.mp4"));
+ Assertions.assertTrue(result.contains("00:05:30"));
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/entity/VideoSigningPendingDownloadQueueDOTest.java b/src/test/java/com/gbg/activate/video/test/entity/VideoSigningPendingDownloadQueueDOTest.java
new file mode 100644
index 0000000..c01f7a0
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/entity/VideoSigningPendingDownloadQueueDOTest.java
@@ -0,0 +1,174 @@
+package com.gbg.activate.video.test.entity;
+
+import com.gbg.activate.video.entity.VideoSigningPendingDownloadQueueDO;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.Date;
+
+public class VideoSigningPendingDownloadQueueDOTest {
+
+ @Test
+ public void testGettersAndSetters() {
+ VideoSigningPendingDownloadQueueDO queue = new VideoSigningPendingDownloadQueueDO();
+ Date now = new Date();
+
+ queue.setSerialNumber(1L);
+ queue.setApplicationNumber("APP001");
+ queue.setTradeNumber("TRADE001");
+ queue.setCustomerNumber("CUST001");
+ queue.setDownloadStatus("PENDING");
+ queue.setEntryTime(now);
+ queue.setInvokeTime(now);
+ queue.setRetryCount(0);
+ queue.setMaxRetry(3);
+ queue.setInvokePriority(1);
+ queue.setErrorMessage("No error");
+
+ Assertions.assertEquals(Long.valueOf(1L), queue.getSerialNumber());
+ Assertions.assertEquals("APP001", queue.getApplicationNumber());
+ Assertions.assertEquals("TRADE001", queue.getTradeNumber());
+ Assertions.assertEquals("CUST001", queue.getCustomerNumber());
+ Assertions.assertEquals("PENDING", queue.getDownloadStatus());
+ Assertions.assertEquals(now, queue.getEntryTime());
+ Assertions.assertEquals(now, queue.getInvokeTime());
+ Assertions.assertEquals(Integer.valueOf(0), queue.getRetryCount());
+ Assertions.assertEquals(Integer.valueOf(3), queue.getMaxRetry());
+ Assertions.assertEquals(Integer.valueOf(1), queue.getInvokePriority());
+ Assertions.assertEquals("No error", queue.getErrorMessage());
+ }
+
+ @Test
+ public void testSettersWithNullValues() {
+ VideoSigningPendingDownloadQueueDO queue = new VideoSigningPendingDownloadQueueDO();
+
+ queue.setSerialNumber(null);
+ queue.setApplicationNumber(null);
+ queue.setTradeNumber(null);
+ queue.setCustomerNumber(null);
+ queue.setDownloadStatus(null);
+ queue.setEntryTime(null);
+ queue.setInvokeTime(null);
+ queue.setRetryCount(null);
+ queue.setMaxRetry(null);
+ queue.setInvokePriority(null);
+ queue.setErrorMessage(null);
+
+ Assertions.assertNull(queue.getSerialNumber());
+ Assertions.assertNull(queue.getApplicationNumber());
+ Assertions.assertNull(queue.getTradeNumber());
+ Assertions.assertNull(queue.getCustomerNumber());
+ Assertions.assertNull(queue.getDownloadStatus());
+ Assertions.assertNull(queue.getEntryTime());
+ Assertions.assertNull(queue.getInvokeTime());
+ Assertions.assertNull(queue.getRetryCount());
+ Assertions.assertNull(queue.getMaxRetry());
+ Assertions.assertNull(queue.getInvokePriority());
+ Assertions.assertNull(queue.getErrorMessage());
+ }
+
+ @Test
+ public void testSettersWithTrimmedValues() {
+ VideoSigningPendingDownloadQueueDO queue = new VideoSigningPendingDownloadQueueDO();
+
+ queue.setApplicationNumber(" APP001 ");
+ queue.setTradeNumber(" TRADE001 ");
+ queue.setCustomerNumber(" CUST001 ");
+ queue.setDownloadStatus(" PENDING ");
+ queue.setErrorMessage(" Error message ");
+
+ Assertions.assertEquals("APP001", queue.getApplicationNumber());
+ Assertions.assertEquals("TRADE001", queue.getTradeNumber());
+ Assertions.assertEquals("CUST001", queue.getCustomerNumber());
+ Assertions.assertEquals("PENDING", queue.getDownloadStatus());
+ Assertions.assertEquals("Error message", queue.getErrorMessage());
+ }
+
+ @Test
+ public void testEqualsWithSameObject() {
+ VideoSigningPendingDownloadQueueDO queue = new VideoSigningPendingDownloadQueueDO();
+ queue.setSerialNumber(1L);
+
+ Assertions.assertTrue(queue.equals(queue));
+ }
+
+ @Test
+ public void testEqualsWithNull() {
+ VideoSigningPendingDownloadQueueDO queue = new VideoSigningPendingDownloadQueueDO();
+
+ Assertions.assertFalse(queue.equals(null));
+ }
+
+ @Test
+ public void testEqualsWithDifferentClass() {
+ VideoSigningPendingDownloadQueueDO queue = new VideoSigningPendingDownloadQueueDO();
+
+ Assertions.assertFalse(queue.equals("string"));
+ }
+
+ @Test
+ public void testEqualsWithSameValues() {
+ VideoSigningPendingDownloadQueueDO queue1 = new VideoSigningPendingDownloadQueueDO();
+ queue1.setSerialNumber(1L);
+ queue1.setApplicationNumber("APP001");
+ queue1.setTradeNumber("TRADE001");
+
+ VideoSigningPendingDownloadQueueDO queue2 = new VideoSigningPendingDownloadQueueDO();
+ queue2.setSerialNumber(1L);
+ queue2.setApplicationNumber("APP001");
+ queue2.setTradeNumber("TRADE001");
+
+ Assertions.assertTrue(queue1.equals(queue2));
+ }
+
+ @Test
+ public void testEqualsWithDifferentValues() {
+ VideoSigningPendingDownloadQueueDO queue1 = new VideoSigningPendingDownloadQueueDO();
+ queue1.setSerialNumber(1L);
+
+ VideoSigningPendingDownloadQueueDO queue2 = new VideoSigningPendingDownloadQueueDO();
+ queue2.setSerialNumber(2L);
+
+ Assertions.assertFalse(queue1.equals(queue2));
+ }
+
+ @Test
+ public void testEqualsWithNullFields() {
+ VideoSigningPendingDownloadQueueDO queue1 = new VideoSigningPendingDownloadQueueDO();
+ VideoSigningPendingDownloadQueueDO queue2 = new VideoSigningPendingDownloadQueueDO();
+
+ Assertions.assertTrue(queue1.equals(queue2));
+ }
+
+ @Test
+ public void testHashCode() {
+ VideoSigningPendingDownloadQueueDO queue = new VideoSigningPendingDownloadQueueDO();
+ queue.setSerialNumber(1L);
+ queue.setApplicationNumber("APP001");
+
+ int hashCode = queue.hashCode();
+ Assertions.assertNotEquals(0, hashCode);
+
+ VideoSigningPendingDownloadQueueDO queue2 = new VideoSigningPendingDownloadQueueDO();
+ queue2.setSerialNumber(1L);
+ queue2.setApplicationNumber("APP001");
+
+ Assertions.assertEquals(queue.hashCode(), queue2.hashCode());
+ }
+
+ @Test
+ public void testToString() {
+ VideoSigningPendingDownloadQueueDO queue = new VideoSigningPendingDownloadQueueDO();
+ queue.setSerialNumber(1L);
+ queue.setApplicationNumber("APP001");
+ queue.setTradeNumber("TRADE001");
+ queue.setDownloadStatus("PENDING");
+
+ String result = queue.toString();
+ Assertions.assertNotNull(result);
+ Assertions.assertTrue(result.contains("VideoSigningPendingDownloadQueueDO"));
+ Assertions.assertTrue(result.contains("APP001"));
+ Assertions.assertTrue(result.contains("TRADE001"));
+ Assertions.assertTrue(result.contains("PENDING"));
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/job/AudioFileCleanupJobTest.java b/src/test/java/com/gbg/activate/video/test/job/AudioFileCleanupJobTest.java
new file mode 100644
index 0000000..90bbae2
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/job/AudioFileCleanupJobTest.java
@@ -0,0 +1,67 @@
+package com.gbg.activate.video.test.job;
+
+import com.gbg.activate.video.job.AudioFileCleanupJob;
+import com.gbg.activate.video.service.IAudioFileCleanupService;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.quartz.JobDetail;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobKey;
+import org.springframework.scheduling.quartz.QuartzJobBean;
+
+import java.lang.reflect.Field;
+
+import static org.mockito.Mockito.*;
+
+public class AudioFileCleanupJobTest {
+
+ private AudioFileCleanupJob job;
+ private IAudioFileCleanupService cleanupService;
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ job = new AudioFileCleanupJob();
+ cleanupService = mock(IAudioFileCleanupService.class);
+
+ // 通过反射注入 mock 对象
+ Field field = AudioFileCleanupJob.class.getDeclaredField("cleanupService");
+ field.setAccessible(true);
+ field.set(job, cleanupService);
+ }
+
+ @Test
+ public void testExecuteInternal() throws Exception {
+ JobExecutionContext context = mock(JobExecutionContext.class);
+ JobDetail jobDetail = mock(JobDetail.class);
+ JobKey jobKey = new JobKey("cleanAudioJobDetail", "VideoGroup");
+
+ when(context.getJobDetail()).thenReturn(jobDetail);
+ when(jobDetail.getKey()).thenReturn(jobKey);
+ when(cleanupService.cleanupOldAudioFiles()).thenReturn(5);
+
+ // 通过反射调用 protected 方法
+ java.lang.reflect.Method method = AudioFileCleanupJob.class.getDeclaredMethod("executeInternal", JobExecutionContext.class);
+ method.setAccessible(true);
+ method.invoke(job, context);
+
+ verify(cleanupService, times(1)).cleanupOldAudioFiles();
+ }
+
+ @Test
+ public void testExecuteInternalWithZeroFiles() throws Exception {
+ JobExecutionContext context = mock(JobExecutionContext.class);
+ JobDetail jobDetail = mock(JobDetail.class);
+ JobKey jobKey = new JobKey("cleanAudioJobDetail", "VideoGroup");
+
+ when(context.getJobDetail()).thenReturn(jobDetail);
+ when(jobDetail.getKey()).thenReturn(jobKey);
+ when(cleanupService.cleanupOldAudioFiles()).thenReturn(0);
+
+ // 通过反射调用 protected 方法
+ java.lang.reflect.Method method = AudioFileCleanupJob.class.getDeclaredMethod("executeInternal", JobExecutionContext.class);
+ method.setAccessible(true);
+ method.invoke(job, context);
+
+ verify(cleanupService, times(1)).cleanupOldAudioFiles();
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/job/ClearExpiredFileJobTest.java b/src/test/java/com/gbg/activate/video/test/job/ClearExpiredFileJobTest.java
new file mode 100644
index 0000000..752131e
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/job/ClearExpiredFileJobTest.java
@@ -0,0 +1,47 @@
+package com.gbg.activate.video.test.job;
+
+import com.gbg.activate.video.job.ClearExpiredFileJob;
+import com.gbg.activate.video.service.IClearExpiredFileService;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.quartz.JobDetail;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobKey;
+
+import java.lang.reflect.Field;
+
+import static org.mockito.Mockito.*;
+
+public class ClearExpiredFileJobTest {
+
+ private ClearExpiredFileJob job;
+ private IClearExpiredFileService clearService;
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ job = new ClearExpiredFileJob();
+ clearService = mock(IClearExpiredFileService.class);
+
+ // 通过反射注入 mock 对象
+ Field field = ClearExpiredFileJob.class.getDeclaredField("clearService");
+ field.setAccessible(true);
+ field.set(job, clearService);
+ }
+
+ @Test
+ public void testExecuteInternal() throws Exception {
+ JobExecutionContext context = mock(JobExecutionContext.class);
+ JobDetail jobDetail = mock(JobDetail.class);
+ JobKey jobKey = new JobKey("ClearExpiredFileJob", "VideoGroup");
+
+ when(context.getJobDetail()).thenReturn(jobDetail);
+ when(jobDetail.getKey()).thenReturn(jobKey);
+
+ // 通过反射调用 protected 方法
+ java.lang.reflect.Method method = ClearExpiredFileJob.class.getDeclaredMethod("executeInternal", JobExecutionContext.class);
+ method.setAccessible(true);
+ method.invoke(job, context);
+
+ verify(clearService, times(1)).clearExpiredFiles();
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/job/RecordingDownloadJobTest.java b/src/test/java/com/gbg/activate/video/test/job/RecordingDownloadJobTest.java
new file mode 100644
index 0000000..cb6eb9d
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/job/RecordingDownloadJobTest.java
@@ -0,0 +1,47 @@
+package com.gbg.activate.video.test.job;
+
+import com.gbg.activate.video.job.RecordingDownloadJob;
+import com.gbg.activate.video.service.IDownloadRecordingTaskService;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.quartz.JobDetail;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobKey;
+
+import java.lang.reflect.Field;
+
+import static org.mockito.Mockito.*;
+
+public class RecordingDownloadJobTest {
+
+ private RecordingDownloadJob job;
+ private IDownloadRecordingTaskService downloadRecordingTaskService;
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ job = new RecordingDownloadJob();
+ downloadRecordingTaskService = mock(IDownloadRecordingTaskService.class);
+
+ // 通过反射注入 mock 对象
+ Field field = RecordingDownloadJob.class.getDeclaredField("downloadRecordingTaskService");
+ field.setAccessible(true);
+ field.set(job, downloadRecordingTaskService);
+ }
+
+ @Test
+ public void testExecuteInternal() throws Exception {
+ JobExecutionContext context = mock(JobExecutionContext.class);
+ JobDetail jobDetail = mock(JobDetail.class);
+ JobKey jobKey = new JobKey("downloadRecordingJobDetail", "VideoGroup");
+
+ when(context.getJobDetail()).thenReturn(jobDetail);
+ when(jobDetail.getKey()).thenReturn(jobKey);
+
+ // 通过反射调用 protected 方法
+ java.lang.reflect.Method method = RecordingDownloadJob.class.getDeclaredMethod("executeInternal", JobExecutionContext.class);
+ method.setAccessible(true);
+ method.invoke(job, context);
+
+ verify(downloadRecordingTaskService, times(1)).processPendingTasks();
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/job/VideoDownloadJobTest.java b/src/test/java/com/gbg/activate/video/test/job/VideoDownloadJobTest.java
new file mode 100644
index 0000000..242ec17
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/job/VideoDownloadJobTest.java
@@ -0,0 +1,47 @@
+package com.gbg.activate.video.test.job;
+
+import com.gbg.activate.video.job.VideoDownloadJob;
+import com.gbg.activate.video.service.IDownloadTaskService;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.quartz.JobDetail;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobKey;
+
+import java.lang.reflect.Field;
+
+import static org.mockito.Mockito.*;
+
+public class VideoDownloadJobTest {
+
+ private VideoDownloadJob job;
+ private IDownloadTaskService downloadService;
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ job = new VideoDownloadJob();
+ downloadService = mock(IDownloadTaskService.class);
+
+ // 通过反射注入 mock 对象
+ Field field = VideoDownloadJob.class.getDeclaredField("downloadService");
+ field.setAccessible(true);
+ field.set(job, downloadService);
+ }
+
+ @Test
+ public void testExecuteInternal() throws Exception {
+ JobExecutionContext context = mock(JobExecutionContext.class);
+ JobDetail jobDetail = mock(JobDetail.class);
+ JobKey jobKey = new JobKey("VideoDownloadJob", "VideoGroup");
+
+ when(context.getJobDetail()).thenReturn(jobDetail);
+ when(jobDetail.getKey()).thenReturn(jobKey);
+
+ // 通过反射调用 protected 方法
+ java.lang.reflect.Method method = VideoDownloadJob.class.getDeclaredMethod("executeInternal", JobExecutionContext.class);
+ method.setAccessible(true);
+ method.invoke(job, context);
+
+ verify(downloadService, times(1)).processPendingTasks();
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/service/AudioFileCleanupServiceImplTest.java b/src/test/java/com/gbg/activate/video/test/service/AudioFileCleanupServiceImplTest.java
new file mode 100644
index 0000000..c3581bc
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/service/AudioFileCleanupServiceImplTest.java
@@ -0,0 +1,81 @@
+package com.gbg.activate.video.test.service;
+
+import com.gbg.activate.video.service.AudioFileCleanupServiceImpl;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import java.lang.reflect.Field;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class AudioFileCleanupServiceImplTest {
+
+ private AudioFileCleanupServiceImpl service;
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ service = new AudioFileCleanupServiceImpl();
+ }
+
+ @Test
+ public void testCleanupWhenDisabled() {
+ ReflectionTestUtils.setField(service, "enabled", false);
+
+ int result = service.cleanupOldAudioFiles();
+
+ Assertions.assertEquals(0, result);
+ }
+
+ @Test
+ public void testCleanupWhenPathNotExists() {
+ ReflectionTestUtils.setField(service, "enabled", true);
+ ReflectionTestUtils.setField(service, "nasPath", "/nonexistent/path");
+ ReflectionTestUtils.setField(service, "retentionDays", 30);
+
+ int result = service.cleanupOldAudioFiles();
+
+ Assertions.assertEquals(0, result);
+ }
+
+ @Test
+ public void testCleanupWhenPathIsNotDirectory() throws Exception {
+ Path tempFile = Files.createTempFile("test", ".txt");
+ try {
+ ReflectionTestUtils.setField(service, "enabled", true);
+ ReflectionTestUtils.setField(service, "nasPath", tempFile.toString());
+ ReflectionTestUtils.setField(service, "retentionDays", 30);
+
+ int result = service.cleanupOldAudioFiles();
+
+ Assertions.assertEquals(0, result);
+ } finally {
+ Files.deleteIfExists(tempFile);
+ }
+ }
+
+ @Test
+ public void testIsAudioFileWithValidExtensions() throws Exception {
+ String[] audioExtensions = {".mp3", ".wav", ".ogg", ".flac", ".m4a", ".aac", ".amr"};
+
+ for (String ext : audioExtensions) {
+ Path file = Paths.get("test" + ext);
+ // 通过反射调用私有方法
+ java.lang.reflect.Method method = AudioFileCleanupServiceImpl.class.getDeclaredMethod("isAudioFile", Path.class);
+ method.setAccessible(true);
+ boolean result = (boolean) method.invoke(service, file);
+ Assertions.assertTrue(result, "Should be audio file: " + ext);
+ }
+ }
+
+ @Test
+ public void testIsAudioFileWithInvalidExtension() throws Exception {
+ Path file = Paths.get("test.txt");
+ java.lang.reflect.Method method = AudioFileCleanupServiceImpl.class.getDeclaredMethod("isAudioFile", Path.class);
+ method.setAccessible(true);
+ boolean result = (boolean) method.invoke(service, file);
+ Assertions.assertFalse(result);
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/service/ClearExpiredFileServiceImplTest.java b/src/test/java/com/gbg/activate/video/test/service/ClearExpiredFileServiceImplTest.java
new file mode 100644
index 0000000..c269050
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/service/ClearExpiredFileServiceImplTest.java
@@ -0,0 +1,89 @@
+package com.gbg.activate.video.test.service;
+
+import com.gbg.activate.video.config.ImageSdkParams;
+import com.gbg.activate.video.entity.VideoSigningDownloadRecordDO;
+import com.gbg.activate.video.mapper.VideoSigningDownloadRecordMapper;
+import com.gbg.activate.video.service.ClearExpiredFileServiceImpl;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.Mockito.*;
+
+public class ClearExpiredFileServiceImplTest {
+
+ private ClearExpiredFileServiceImpl service;
+ private ImageSdkParams params;
+ private VideoSigningDownloadRecordMapper recordMapper;
+
+ @BeforeEach
+ public void setUp() {
+ service = new ClearExpiredFileServiceImpl();
+ params = mock(ImageSdkParams.class);
+ recordMapper = mock(VideoSigningDownloadRecordMapper.class);
+
+ // 通过反射注入 mock 对象
+ try {
+ java.lang.reflect.Field paramsField = ClearExpiredFileServiceImpl.class.getDeclaredField("params");
+ paramsField.setAccessible(true);
+ paramsField.set(service, params);
+
+ java.lang.reflect.Field mapperField = ClearExpiredFileServiceImpl.class.getDeclaredField("recordMapper");
+ mapperField.setAccessible(true);
+ mapperField.set(service, recordMapper);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void testClearExpiredFilesWithNoRecords() {
+ when(params.getValidDays()).thenReturn(30);
+ when(recordMapper.listExpiredRecords(30)).thenReturn(new ArrayList<>());
+
+ service.clearExpiredFiles();
+
+ verify(recordMapper, times(1)).listExpiredRecords(30);
+ }
+
+ @Test
+ public void testClearExpiredFilesWithRecords() {
+ when(params.getValidDays()).thenReturn(30);
+ when(params.getFileSavePath()).thenReturn("/tmp");
+
+ List records = new ArrayList<>();
+ VideoSigningDownloadRecordDO record = new VideoSigningDownloadRecordDO();
+ record.setApplicationNumber("APP001");
+ record.setImageId("IMG001");
+ record.setImageName("test.mp4");
+ records.add(record);
+
+ when(recordMapper.listExpiredRecords(30)).thenReturn(records);
+
+ service.clearExpiredFiles();
+
+ verify(recordMapper, times(1)).listExpiredRecords(30);
+ verify(recordMapper, times(1)).deleteByPrimaryKey("APP001", "IMG001");
+ }
+
+ @Test
+ public void testClearExpiredFilesWithError() {
+ when(params.getValidDays()).thenReturn(30);
+ when(params.getFileSavePath()).thenReturn(null); // 这将导致异常
+
+ List records = new ArrayList<>();
+ VideoSigningDownloadRecordDO record = new VideoSigningDownloadRecordDO();
+ record.setApplicationNumber("APP001");
+ record.setImageId("IMG001");
+ record.setImageName("test.mp4");
+ records.add(record);
+
+ when(recordMapper.listExpiredRecords(30)).thenReturn(records);
+
+ service.clearExpiredFiles();
+
+ verify(recordMapper, times(1)).listExpiredRecords(30);
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/service/DownloadRecordingTaskServiceImplTest.java b/src/test/java/com/gbg/activate/video/test/service/DownloadRecordingTaskServiceImplTest.java
new file mode 100644
index 0000000..ec8b5a5
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/service/DownloadRecordingTaskServiceImplTest.java
@@ -0,0 +1,168 @@
+package com.gbg.activate.video.test.service;
+
+import com.gbg.activate.video.config.ImageSdkParams;
+import com.gbg.activate.video.constant.DownloadStatus;
+import com.gbg.activate.video.entity.RecordingDownloadDO;
+import com.gbg.activate.video.entity.RecordingPendingDownloadQueueDO;
+import com.gbg.activate.video.mapper.RecordingDownloadMapper;
+import com.gbg.activate.video.mapper.RecordingPendingDownloadQueueMapper;
+import com.gbg.activate.video.service.DownloadRecordingTaskServiceImpl;
+import com.icms.common.bean.SdkImage;
+import com.icms.common.bean.SdkResult;
+import com.icms.sdk.inter.ImageSdkInter;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.Mockito.*;
+
+public class DownloadRecordingTaskServiceImplTest {
+
+ private DownloadRecordingTaskServiceImpl service;
+ private ImageSdkParams params;
+ private RecordingPendingDownloadQueueMapper taskMapper;
+ private RecordingDownloadMapper recordMapper;
+ private ImageSdkInter imageService;
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ service = new DownloadRecordingTaskServiceImpl();
+ params = mock(ImageSdkParams.class);
+ taskMapper = mock(RecordingPendingDownloadQueueMapper.class);
+ recordMapper = mock(RecordingDownloadMapper.class);
+ imageService = mock(ImageSdkInter.class);
+
+ // 通过反射注入 mock 对象
+ injectField("params", params);
+ injectField("taskMapper", taskMapper);
+ injectField("recordMapper", recordMapper);
+ injectField("imageService", imageService);
+ injectField("serverAddress", "localhost");
+ injectField("serverPort", "8080");
+ }
+
+ private void injectField(String fieldName, Object value) throws Exception {
+ java.lang.reflect.Field field = DownloadRecordingTaskServiceImpl.class.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ field.set(service, value);
+ }
+
+ @Test
+ public void testProcessPendingTasksWithNoTasks() {
+ when(taskMapper.fetchPendingTasks()).thenReturn(new ArrayList<>());
+
+ service.processPendingTasks();
+
+ verify(taskMapper, times(1)).fetchPendingTasks();
+ }
+
+ @Test
+ public void testProcessSingleTaskWithNullTask() throws Exception {
+ java.lang.reflect.Method method = DownloadRecordingTaskServiceImpl.class.getDeclaredMethod("processSingleTask", RecordingPendingDownloadQueueDO.class);
+ method.setAccessible(true);
+
+ method.invoke(service, (RecordingPendingDownloadQueueDO) null);
+
+ verifyNoInteractions(taskMapper, recordMapper, imageService);
+ }
+
+ @Test
+ public void testProcessSingleTaskWithEmptyImageId() throws Exception {
+ RecordingPendingDownloadQueueDO task = new RecordingPendingDownloadQueueDO();
+ task.setImageId("");
+
+ java.lang.reflect.Method method = DownloadRecordingTaskServiceImpl.class.getDeclaredMethod("processSingleTask", RecordingPendingDownloadQueueDO.class);
+ method.setAccessible(true);
+
+ method.invoke(service, task);
+
+ verify(taskMapper, never()).updateByPrimaryKeySelective(any());
+ }
+
+ @Test
+ public void testProcessSingleTaskSuccess() throws Exception {
+ RecordingPendingDownloadQueueDO task = new RecordingPendingDownloadQueueDO();
+ task.setApplicationNumber("APP001");
+ task.setCallId("CALL001");
+ task.setImageId("IMG001");
+ task.setRetryCount(0);
+ task.setMaxRetry(3);
+
+ SdkResult result = new SdkResult();
+ result.setRetCode("00000");
+ List images = new ArrayList<>();
+ SdkImage image = new SdkImage();
+ image.setImageId("IMG001");
+ image.setImageName("test.mp3");
+ image.setImageSize("1024");
+ image.setCreateDate("2025-01-01");
+ images.add(image);
+ result.setSdkImages(images);
+
+ when(params.getSysNo1()).thenReturn("SYS001");
+ when(params.getFileSavePath1()).thenReturn("/tmp");
+ when(imageService.downloadOnePageBigImageByImageId(anyString(), anyString(), anyString())).thenReturn(result);
+
+ java.lang.reflect.Method method = DownloadRecordingTaskServiceImpl.class.getDeclaredMethod("processSingleTask", RecordingPendingDownloadQueueDO.class);
+ method.setAccessible(true);
+
+ method.invoke(service, task);
+
+ verify(taskMapper, atLeastOnce()).updateByPrimaryKeySelective(any());
+ verify(recordMapper, times(1)).insert(any(RecordingDownloadDO.class));
+ }
+
+ @Test
+ public void testProcessSingleTaskFailed() throws Exception {
+ RecordingPendingDownloadQueueDO task = new RecordingPendingDownloadQueueDO();
+ task.setApplicationNumber("APP001");
+ task.setImageId("IMG001");
+ task.setRetryCount(0);
+ task.setMaxRetry(3);
+
+ SdkResult result = new SdkResult();
+ result.setRetCode("99999");
+ result.setRetMessage("Download failed");
+
+ when(params.getSysNo1()).thenReturn("SYS001");
+ when(params.getFileSavePath1()).thenReturn("/tmp");
+ when(imageService.downloadOnePageBigImageByImageId(anyString(), anyString(), anyString())).thenReturn(result);
+
+ java.lang.reflect.Method method = DownloadRecordingTaskServiceImpl.class.getDeclaredMethod("processSingleTask", RecordingPendingDownloadQueueDO.class);
+ method.setAccessible(true);
+
+ try {
+ method.invoke(service, task);
+ } catch (Exception e) {
+ // Expected exception
+ }
+ }
+
+ @Test
+ public void testHandleFailedTaskMaxRetryReached() throws Exception {
+ RecordingPendingDownloadQueueDO task = new RecordingPendingDownloadQueueDO();
+ task.setRetryCount(3);
+ task.setMaxRetry(3);
+
+ java.lang.reflect.Method method = DownloadRecordingTaskServiceImpl.class.getDeclaredMethod("handleFailedTask", RecordingPendingDownloadQueueDO.class, String.class);
+ method.setAccessible(true);
+ method.invoke(service, task, "Error message");
+
+ verify(taskMapper, times(1)).updateByPrimaryKeySelective(task);
+ }
+
+ @Test
+ public void testHandleFailedTaskRetryAvailable() throws Exception {
+ RecordingPendingDownloadQueueDO task = new RecordingPendingDownloadQueueDO();
+ task.setRetryCount(1);
+ task.setMaxRetry(3);
+
+ java.lang.reflect.Method method = DownloadRecordingTaskServiceImpl.class.getDeclaredMethod("handleFailedTask", RecordingPendingDownloadQueueDO.class, String.class);
+ method.setAccessible(true);
+ method.invoke(service, task, "Error message");
+
+ verify(taskMapper, times(1)).updateByPrimaryKeySelective(task);
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/service/DownloadTaskServiceImplTest.java b/src/test/java/com/gbg/activate/video/test/service/DownloadTaskServiceImplTest.java
new file mode 100644
index 0000000..5425f91
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/service/DownloadTaskServiceImplTest.java
@@ -0,0 +1,178 @@
+package com.gbg.activate.video.test.service;
+
+import com.gbg.activate.video.config.ImageSdkParams;
+import com.gbg.activate.video.constant.DownloadStatus;
+import com.gbg.activate.video.entity.VideoSigningDownloadRecordDO;
+import com.gbg.activate.video.entity.VideoSigningPendingDownloadQueueDO;
+import com.gbg.activate.video.mapper.VideoSigningDownloadRecordMapper;
+import com.gbg.activate.video.mapper.VideoSigningPendingDownloadQueueMapper;
+import com.gbg.activate.video.service.DownloadTaskServiceImpl;
+import com.icms.common.bean.SdkImage;
+import com.icms.common.bean.SdkResult;
+import com.icms.sdk.inter.ImageSdkInter;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.Mockito.*;
+
+public class DownloadTaskServiceImplTest {
+
+ private DownloadTaskServiceImpl service;
+ private ImageSdkParams params;
+ private VideoSigningPendingDownloadQueueMapper taskMapper;
+ private VideoSigningDownloadRecordMapper recordMapper;
+ private ImageSdkInter imageService;
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ service = new DownloadTaskServiceImpl();
+ params = mock(ImageSdkParams.class);
+ taskMapper = mock(VideoSigningPendingDownloadQueueMapper.class);
+ recordMapper = mock(VideoSigningDownloadRecordMapper.class);
+ imageService = mock(ImageSdkInter.class);
+
+ // 通过反射注入 mock 对象
+ injectField("params", params);
+ injectField("taskMapper", taskMapper);
+ injectField("recordMapper", recordMapper);
+ injectField("imageService", imageService);
+ injectField("serverAddress", "localhost");
+ injectField("serverPort", "8080");
+ }
+
+ private void injectField(String fieldName, Object value) throws Exception {
+ java.lang.reflect.Field field = DownloadTaskServiceImpl.class.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ field.set(service, value);
+ }
+
+ @Test
+ public void testProcessPendingTasksWithNoTasks() {
+ when(taskMapper.fetchPendingTasks()).thenReturn(new ArrayList<>());
+
+ service.processPendingTasks();
+
+ verify(taskMapper, times(1)).fetchPendingTasks();
+ }
+
+ @Test
+ public void testProcessSingleTaskSuccess() throws Exception {
+ VideoSigningPendingDownloadQueueDO task = new VideoSigningPendingDownloadQueueDO();
+ task.setSerialNumber(1L);
+ task.setApplicationNumber("APP001");
+ task.setTradeNumber("TRADE001");
+ task.setCustomerNumber("CUST001");
+ task.setRetryCount(0);
+ task.setMaxRetry(3);
+
+ SdkResult result = new SdkResult();
+ result.setRetCode("00000");
+ List images = new ArrayList<>();
+ SdkImage image = new SdkImage();
+ image.setImageId("IMG001");
+ image.setImageName("test.txt"); // 非 mp4 文件
+ image.setImageSize("1024");
+ image.setCreateDate("2025-01-01");
+ images.add(image);
+ result.setSdkImages(images);
+
+ when(params.getSysNo()).thenReturn("SYS001");
+ when(params.getFileSavePath()).thenReturn("/tmp");
+ when(imageService.downloadOneStoreBigImageByTradeNo(anyString(), anyString(), anyString(), anyString())).thenReturn(result);
+
+ java.lang.reflect.Method method = DownloadTaskServiceImpl.class.getDeclaredMethod("processSingleTask", VideoSigningPendingDownloadQueueDO.class);
+ method.setAccessible(true);
+
+ method.invoke(service, task);
+
+ verify(recordMapper, times(1)).deleteByApplicationNumber("APP001");
+ verify(recordMapper, times(1)).insert(any(VideoSigningDownloadRecordDO.class));
+ verify(taskMapper, times(1)).deleteByPrimaryKey(1L);
+ }
+
+ @Test
+ public void testProcessSingleTaskWithMp4File() throws Exception {
+ VideoSigningPendingDownloadQueueDO task = new VideoSigningPendingDownloadQueueDO();
+ task.setSerialNumber(1L);
+ task.setApplicationNumber("APP001");
+ task.setTradeNumber("TRADE001");
+ task.setCustomerNumber("CUST001");
+
+ SdkResult result = new SdkResult();
+ result.setRetCode("00000");
+ List images = new ArrayList<>();
+ SdkImage image = new SdkImage();
+ image.setImageId("IMG001");
+ image.setImageName("test.mp4");
+ image.setImageSize("1024");
+ image.setCreateDate("2025-01-01");
+ images.add(image);
+ result.setSdkImages(images);
+
+ when(params.getSysNo()).thenReturn("SYS001");
+ when(params.getFileSavePath()).thenReturn("/tmp");
+ when(imageService.downloadOneStoreBigImageByTradeNo(anyString(), anyString(), anyString(), anyString())).thenReturn(result);
+
+ java.lang.reflect.Method method = DownloadTaskServiceImpl.class.getDeclaredMethod("processSingleTask", VideoSigningPendingDownloadQueueDO.class);
+ method.setAccessible(true);
+
+ // MP4 文件会尝试解析时长,但文件不存在会捕获异常
+ method.invoke(service, task);
+
+ verify(recordMapper, atLeastOnce()).insert(any(VideoSigningDownloadRecordDO.class));
+ }
+
+ @Test
+ public void testProcessSingleTaskFailed() throws Exception {
+ VideoSigningPendingDownloadQueueDO task = new VideoSigningPendingDownloadQueueDO();
+ task.setApplicationNumber("APP001");
+ task.setRetryCount(0);
+ task.setMaxRetry(3);
+
+ SdkResult result = new SdkResult();
+ result.setRetCode("99999");
+ result.setRetMessage("Download failed");
+
+ when(params.getSysNo()).thenReturn("SYS001");
+ when(params.getFileSavePath()).thenReturn("/tmp");
+ when(imageService.downloadOneStoreBigImageByTradeNo(anyString(), anyString(), anyString(), anyString())).thenReturn(result);
+
+ java.lang.reflect.Method method = DownloadTaskServiceImpl.class.getDeclaredMethod("processSingleTask", VideoSigningPendingDownloadQueueDO.class);
+ method.setAccessible(true);
+
+ try {
+ method.invoke(service, task);
+ } catch (Exception e) {
+ // Expected exception
+ }
+ }
+
+ @Test
+ public void testHandleFailedTaskMaxRetryReached() throws Exception {
+ VideoSigningPendingDownloadQueueDO task = new VideoSigningPendingDownloadQueueDO();
+ task.setRetryCount(3);
+ task.setMaxRetry(3);
+
+ java.lang.reflect.Method method = DownloadTaskServiceImpl.class.getDeclaredMethod("handleFailedTask", VideoSigningPendingDownloadQueueDO.class, String.class);
+ method.setAccessible(true);
+ method.invoke(service, task, "Error message");
+
+ verify(taskMapper, times(1)).updateByPrimaryKeySelective(task);
+ }
+
+ @Test
+ public void testHandleFailedTaskRetryAvailable() throws Exception {
+ VideoSigningPendingDownloadQueueDO task = new VideoSigningPendingDownloadQueueDO();
+ task.setRetryCount(1);
+ task.setMaxRetry(3);
+
+ java.lang.reflect.Method method = DownloadTaskServiceImpl.class.getDeclaredMethod("handleFailedTask", VideoSigningPendingDownloadQueueDO.class, String.class);
+ method.setAccessible(true);
+ method.invoke(service, task, "Error message");
+
+ verify(taskMapper, times(1)).updateByPrimaryKeySelective(task);
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/service/RecordingViewServiceImplTest.java b/src/test/java/com/gbg/activate/video/test/service/RecordingViewServiceImplTest.java
new file mode 100644
index 0000000..75ec32e
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/service/RecordingViewServiceImplTest.java
@@ -0,0 +1,48 @@
+package com.gbg.activate.video.test.service;
+
+import com.gbg.activate.video.config.ImageSdkParams;
+import com.gbg.activate.video.service.RecordingViewServiceImpl;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.core.io.Resource;
+
+import java.net.MalformedURLException;
+
+import static org.mockito.Mockito.*;
+
+public class RecordingViewServiceImplTest {
+
+ private RecordingViewServiceImpl service;
+ private ImageSdkParams params;
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ service = new RecordingViewServiceImpl();
+ params = mock(ImageSdkParams.class);
+
+ // 通过反射注入 mock 对象
+ java.lang.reflect.Field field = RecordingViewServiceImpl.class.getDeclaredField("params");
+ field.setAccessible(true);
+ field.set(service, params);
+ }
+
+ @Test
+ public void testViewFileSuccess() throws MalformedURLException {
+ when(params.getFileSavePath()).thenReturn("/tmp");
+
+ Resource resource = service.viewFile("test.mp4");
+
+ Assertions.assertNotNull(resource);
+ verify(params, times(1)).getFileSavePath();
+ }
+
+ @Test
+ public void testViewFileWithDifferentFileName() throws MalformedURLException {
+ when(params.getFileSavePath()).thenReturn("/data/videos");
+
+ Resource resource = service.viewFile("recording.wav");
+
+ Assertions.assertNotNull(resource);
+ }
+}
diff --git a/src/test/java/com/gbg/activate/video/test/service/VideoViewServiceImplTest.java b/src/test/java/com/gbg/activate/video/test/service/VideoViewServiceImplTest.java
new file mode 100644
index 0000000..753412f
--- /dev/null
+++ b/src/test/java/com/gbg/activate/video/test/service/VideoViewServiceImplTest.java
@@ -0,0 +1,48 @@
+package com.gbg.activate.video.test.service;
+
+import com.gbg.activate.video.config.ImageSdkParams;
+import com.gbg.activate.video.service.VideoViewServiceImpl;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.core.io.Resource;
+
+import java.net.MalformedURLException;
+
+import static org.mockito.Mockito.*;
+
+public class VideoViewServiceImplTest {
+
+ private VideoViewServiceImpl service;
+ private ImageSdkParams params;
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ service = new VideoViewServiceImpl();
+ params = mock(ImageSdkParams.class);
+
+ // 通过反射注入 mock 对象
+ java.lang.reflect.Field field = VideoViewServiceImpl.class.getDeclaredField("params");
+ field.setAccessible(true);
+ field.set(service, params);
+ }
+
+ @Test
+ public void testViewFileSuccess() throws MalformedURLException {
+ when(params.getFileSavePath()).thenReturn("/tmp");
+
+ Resource resource = service.viewFile("test.mp4");
+
+ Assertions.assertNotNull(resource);
+ verify(params, times(1)).getFileSavePath();
+ }
+
+ @Test
+ public void testViewFileWithDifferentFileName() throws MalformedURLException {
+ when(params.getFileSavePath()).thenReturn("/data/videos");
+
+ Resource resource = service.viewFile("video.mp4");
+
+ Assertions.assertNotNull(resource);
+ }
+}