first commit

This commit is contained in:
lihansani
2026-07-13 13:25:21 +08:00
commit 3aa180bbd2
285 changed files with 22351 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
{
"permissions": {
"allow": [
"Bash(ls \"e:\\\\projects\\\\wxwx\\\\projects_job\\\\UniversalTestSoftware\\\\UDP_Projects\\\\Code\\\\Client\\\\Back_end\\\\\")",
"Read(//e/projects/wxwx/projects_job/UniversalTestSoftware/UDP_Projects/Code/Client/**)"
]
}
}

2
.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
/mvnw text eol=lf
*.cmd text eol=crlf

33
.gitignore vendored Normal file
View File

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

19
.mvn/wrapper/maven-wrapper.properties vendored Normal file
View File

@@ -0,0 +1,19 @@
# 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
#
# http://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.
wrapperVersion=3.3.2
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip

BIN
doc/协议描述.pdf Normal file

Binary file not shown.

259
mvnw vendored Normal file
View File

@@ -0,0 +1,259 @@
#!/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
#
# http://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.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.3.2
#
# Optional ENV vars
# -----------------
# JAVA_HOME - location of a JDK home dir, required when download maven via java source
# MVNW_REPOURL - repo url base for downloading maven distribution
# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
# ----------------------------------------------------------------------------
set -euf
[ "${MVNW_VERBOSE-}" != debug ] || set -x
# OS specific support.
native_path() { printf %s\\n "$1"; }
case "$(uname)" in
CYGWIN* | MINGW*)
[ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
native_path() { cygpath --path --windows "$1"; }
;;
esac
# set JAVACMD and JAVACCMD
set_java_home() {
# For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
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"
JAVACCMD="$JAVA_HOME/jre/sh/javac"
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACCMD="$JAVA_HOME/bin/javac"
if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
return 1
fi
fi
else
JAVACMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v java
)" || :
JAVACCMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v javac
)" || :
if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
return 1
fi
fi
}
# hash string like Java String::hashCode
hash_string() {
str="${1:-}" h=0
while [ -n "$str" ]; do
char="${str%"${str#?}"}"
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
str="${str#?}"
done
printf %x\\n $h
}
verbose() { :; }
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
die() {
printf %s\\n "$1" >&2
exit 1
}
trim() {
# MWRAPPER-139:
# Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
# Needed for removing poorly interpreted newline sequences when running in more
# exotic environments such as mingw bash on Windows.
printf "%s" "${1}" | tr -d '[:space:]'
}
# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
while IFS="=" read -r key value; do
case "${key-}" in
distributionUrl) distributionUrl=$(trim "${value-}") ;;
distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
esac
done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
case "${distributionUrl##*/}" in
maven-mvnd-*bin.*)
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
*)
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
distributionPlatform=linux-amd64
;;
esac
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
;;
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
esac
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
distributionUrlName="${distributionUrl##*/}"
distributionUrlNameMain="${distributionUrlName%.*}"
distributionUrlNameMain="${distributionUrlNameMain%-bin}"
MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
exec_maven() {
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
}
if [ -d "$MAVEN_HOME" ]; then
verbose "found existing MAVEN_HOME at $MAVEN_HOME"
exec_maven "$@"
fi
case "${distributionUrl-}" in
*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
esac
# prepare tmp dir
if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
trap clean HUP INT TERM EXIT
else
die "cannot create temp dir"
fi
mkdir -p -- "${MAVEN_HOME%/*}"
# Download and Install Apache Maven
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
verbose "Downloading from: $distributionUrl"
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
# select .zip or .tar.gz
if ! command -v unzip >/dev/null; then
distributionUrl="${distributionUrl%.zip}.tar.gz"
distributionUrlName="${distributionUrl##*/}"
fi
# verbose opt
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
# normalize http auth
case "${MVNW_PASSWORD:+has-password}" in
'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
esac
if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
verbose "Found wget ... using wget"
wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
verbose "Found curl ... using curl"
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
elif set_java_home; then
verbose "Falling back to use Java to download"
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
cat >"$javaSource" <<-END
public class Downloader extends java.net.Authenticator
{
protected java.net.PasswordAuthentication getPasswordAuthentication()
{
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
}
public static void main( String[] args ) throws Exception
{
setDefault( new Downloader() );
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
}
}
END
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
verbose " - Compiling Downloader.java ..."
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
verbose " - Running Downloader.java ..."
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
fi
# If specified, validate the SHA-256 sum of the Maven distribution zip file
if [ -n "${distributionSha256Sum-}" ]; then
distributionSha256Result=false
if [ "$MVN_CMD" = mvnd.sh ]; then
echo "Checksum validation is not supported for maven-mvnd." >&2
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
elif command -v sha256sum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
elif command -v shasum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
fi
if [ $distributionSha256Result = false ]; then
echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
exit 1
fi
fi
# unzip and move
if command -v unzip >/dev/null; then
unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
else
tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
fi
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
clean || :
exec_maven "$@"

149
mvnw.cmd vendored Normal file
View File

@@ -0,0 +1,149 @@
<# : batch portion
@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 http://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 Apache Maven Wrapper startup batch script, version 3.3.2
@REM
@REM Optional ENV vars
@REM MVNW_REPOURL - repo url base for downloading maven distribution
@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
@REM ----------------------------------------------------------------------------
@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
@SET __MVNW_CMD__=
@SET __MVNW_ERROR__=
@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
@SET PSModulePath=
@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
)
@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
@SET __MVNW_PSMODULEP_SAVE=
@SET __MVNW_ARG0_NAME__=
@SET MVNW_USERNAME=
@SET MVNW_PASSWORD=
@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
@echo Cannot start maven from wrapper >&2 && exit /b 1
@GOTO :EOF
: end batch / begin powershell #>
$ErrorActionPreference = "Stop"
if ($env:MVNW_VERBOSE -eq "true") {
$VerbosePreference = "Continue"
}
# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
if (!$distributionUrl) {
Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
}
switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
"maven-mvnd-*" {
$USE_MVND = $true
$distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
$MVN_CMD = "mvnd.cmd"
break
}
default {
$USE_MVND = $false
$MVN_CMD = $script -replace '^mvnw','mvn'
break
}
}
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
if ($env:MVNW_REPOURL) {
$MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
$distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
}
$distributionUrlName = $distributionUrl -replace '^.*/',''
$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
if ($env:MAVEN_USER_HOME) {
$MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain"
}
$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
exit $?
}
if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
}
# prepare tmp dir
$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
trap {
if ($TMP_DOWNLOAD_DIR.Exists) {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
}
New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
# Download and Install Apache Maven
Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
Write-Verbose "Downloading from: $distributionUrl"
Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
$webclient = New-Object System.Net.WebClient
if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
$webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
# If specified, validate the SHA-256 sum of the Maven distribution zip file
$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
if ($distributionSha256Sum) {
if ($USE_MVND) {
Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
}
Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
}
}
# unzip and move
Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
try {
Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
} catch {
if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
Write-Error "fail to move MAVEN_HOME"
}
} finally {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"

275
pom.xml Normal file
View File

@@ -0,0 +1,275 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>universaltestsoftware_client_api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>universaltestsoftware_client_api</name>
<description>universaltestsoftware_client_api</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!-- Jackson Annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.17.1</version>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>5.2.1</version>
</dependency>
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.9</version>
</dependency>
<!-- Jackson YAML 数据格式支持 (对应 YAMLMapper) -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>2.17.1</version>
</dependency>
<!-- Jackson Java Properties 数据格式支持 (对应 JavaPropsMapper) -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-properties</artifactId>
<version>2.17.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.14.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>4.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.58.Final</version>
</dependency>
<!-- Spring WebSocket 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.3.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.32</version> <!-- 使用最新稳定版 -->
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>3.0.0</version>
</dependency>
<!-- 官方UI包 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
</dependency>
<!-- Hutool 工具包 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.20</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version> <!-- 根据需要选择合适版本 -->
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.sun.istack</groupId>
<artifactId>istack-commons-runtime</artifactId>
<version>3.0.11</version> <!-- 确保版本与 jaxb-core 兼容 -->
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version> <!-- 确保版本与 jaxb-core 兼容 -->
</dependency>
<dependency>
<groupId>io.reactivex.rxjava3</groupId>
<artifactId>rxjava</artifactId>
<version>3.1.6</version> <!-- 确保版本与 jaxb-core 兼容 -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-loader</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.yeauty</groupId>
<artifactId>netty-websocket-spring-boot-starter</artifactId>
<version>0.12.0</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- Spring Cloud 版本控制 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2020.0.3</version> <!-- Ilford 系列最后一个稳定版 -->
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- <plugin>-->
<!-- <groupId>org.apache.maven.plugins</groupId>-->
<!-- <artifactId>maven-compiler-plugin</artifactId>-->
<!-- <configuration>-->
<!-- <source>9</source>-->
<!-- <target>9</target>-->
<!-- </configuration>-->
<!-- </plugin>-->
</plugins>
</build>
</project>

View File

@@ -0,0 +1,6 @@
package com.cbsd.client;
public interface Test {
public String test();
}

View File

@@ -0,0 +1,29 @@
package com.cbsd.client.branch;
import java.util.Map;
/**
* 分支条件脚本
* 根据通道绑定的ICD的协议中的字段对数据进行判断返回需要跳转的指令名称
*/
public interface IBranchConditionInterface {
/**
* 分支条件
* @param originalCommand 原始指令数据
* @param preTreatmentCommand 预处理指令数据,若无预处理,则为原始指令数据
* @param repeatCount 重复次数
* @param hitCount 命中次数
* @param latestHitTime 最后命中时间
* @param dataMap 数据集合key为协议字段属性名labelvalue为物理值
* @return 需要跳转的指令名称,为空则为不跳转
*/
String branchCondition(String originalCommand, String preTreatmentCommand, int repeatCount, int hitCount, String latestHitTime, Map<String, String> dataMap);
/**
* 描述
*
* @return 描述内容
*/
String comment();
}

View File

@@ -0,0 +1,30 @@
package com.cbsd.client.check;
import java.util.List;
import java.util.Map;
/**
* 检查脚本接口
* 根据通道绑定的ICD的协议中的字段对数据进行检查并写入日志
*/
public interface ICheckInterface {
/**
* 检查
* @param originalCommand 原始指令数据
* @param preTreatmentCommand 预处理指令数据,若无预处理,则为原始指令数据
* @param repeatCount 重复次数
* @param hitCount 命中次数
* @param latestHitTime 最后命中时间
* @param dataMap 数据集合key为协议字段属性名labelvalue为物理值
* @return 日志信息列表
*/
List<String> check(String originalCommand, String preTreatmentCommand, int repeatCount, int hitCount, String latestHitTime, Map<String, String> dataMap);
/**
* 描述
*
* @return 描述内容
*/
String comment();
}

View File

@@ -0,0 +1,23 @@
package com.cbsd.client.parse;
public interface IParseDataInterface {
/**
* 从数据解析物理值
*
* @param sn 当前字段序号
* @param sourceData 源数据
* @param fieldData 当前字段数据
* @param endian BIG大端序 LITTLE小端序
* @param binStr 二进制字符串
* @return 解析后的数据值
*/
String parsePhysicalFromData(int sn, byte[] sourceData, byte[] fieldData, String endian, String binStr);
/**
* 当前解析描述
*
* @return 描述内容
*/
String comment();
}

View File

@@ -0,0 +1,4 @@
package com.cbsd.client.pretreatment;
public class CalculateUtils {
}

View File

@@ -0,0 +1,30 @@
package com.cbsd.client.pretreatment;
import java.util.Map;
/**
* 预处理脚本接口
* 指令数据、命中次数、命中时间、重复次数、 校验(内置方法)?
*/
public interface IPreTreatmentInterface {
/**
* 预处理
*
* @param command 指令内容
* @param repeatCount 重复次数
* @param hitCount 命中次数
* @param latestHitTime 最后命中时间
* @param dataMap 数据集合key为协议字段属性名labelvalue为物理值
* @param calculateUtils 计算工具类
* @return 结果
*/
String pretreatment(String command, int repeatCount, int hitCount, String latestHitTime, Map<String, String> dataMap, CalculateUtils calculateUtils);
/**
* 描述
*
* @return 描述内容
*/
String comment();
}

View File

@@ -0,0 +1,20 @@
package com.cbsd.client.verification;
public interface IVerificationInterface {
/**
* 校验
*
* @param data 校验数据
* @param verify 校验位
* @param verifyUtils 校验工具类
* @return 校验结果
*/
boolean verification(byte[] data, byte[] verify, VerifyUtils verifyUtils);
/**
* 当前解析描述
*
* @return 描述内容
*/
String comment();
}

View File

@@ -0,0 +1,55 @@
package com.cbsd.client.verification;
public class VerifyUtils {
/**
* 验证数据的CRC16校验值
*
* @param data 包含CRC校验值的数据CRC在数据末尾2字节
* @return 校验结果true表示校验通过false表示校验失败
*/
public boolean verifyCRC(byte[] data) {
if (data == null || data.length < 2) {
return false;
}
// 提取数据部分不包含CRC
byte[] dataWithoutCRC = new byte[data.length - 2];
System.arraycopy(data, 0, dataWithoutCRC, 0, data.length - 2);
// 计算CRC
byte[] calculatedCRC = calculateCRC(dataWithoutCRC);
// 比较计算得到的CRC与数据中包含的CRC
return calculatedCRC[0] == data[data.length - 2] &&
calculatedCRC[1] == data[data.length - 1];
}
/**
* 计算Modbus CRC16校验值
*
* @param data 待校验的数据
* @return CRC16校验值2字节数组
*/
private byte[] calculateCRC(byte[] data) {
int crc = 0xFFFF;
for (byte b : data) {
crc ^= (b & 0xFF);
for (int i = 0; i < 8; i++) {
if ((crc & 0x0001) != 0) {
crc >>= 1;
crc ^= 0xA001;
} else {
crc >>= 1;
}
}
}
// 将CRC转换为字节数组低字节在前高字节在后
byte[] result = new byte[2];
result[0] = (byte) (crc & 0xFF);
result[1] = (byte) ((crc >> 8) & 0xFF);
return result;
}
}

View File

@@ -0,0 +1,59 @@
package com.cbsd.universaltestsoftware_client;
import com.cbsd.universaltestsoftware_client.util.DynamicClassLoader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class DynamicClassBootstrap {
@Value("${cbsd.uploadfilesrootpath}")
private String rootPath;
// 最终缓存:全限定类名 → Class<?>,运行时直接拿
public static final Map<String, Class<?>> CLAZZ_CACHE = new ConcurrentHashMap<>();
// @PostConstruct // Spring 容器初始化完成后立即执行
public void loadAllCompiledClasses() throws Exception {
Path root = Paths.get(rootPath);
if (!Files.exists(root)) {
return;
}
// 自定义类加载器
DynamicClassLoader loader = new DynamicClassLoader(rootPath);
// 遍历目录树
Files.walk(root)
.filter(p -> p.toString().endsWith(".class"))
.forEach(p -> {
// 把文件路径 → 全限定类名
String fullName = pathToFqn(root, p);
try {
Class<?> clazz = loader.loadClass(fullName);
CLAZZ_CACHE.put(fullName, clazz);
} catch (ClassNotFoundException e) {
// 记录日志即可
e.printStackTrace();
}
});
System.out.println("已预加载 class 数量:" + CLAZZ_CACHE.size());
}
// 工具:把文件路径转换成 com.xxx.yyy.ClassName
private String pathToFqn(Path root, Path classFile) {
String relative = root.relativize(classFile).toString();
return relative
.replace(File.separatorChar, '.')
.replace(".class", "");
}
}

View File

@@ -0,0 +1,21 @@
package com.cbsd.universaltestsoftware_client;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@MapperScan("com.cbsd.*.mapper")
@ComponentScan("com.cbsd.*")
@EnableAsync
@EnableScheduling // 开启定时任务功能
public class UniversaltestsoftwareClientApiApplication {
public static void main(String[] args) {
SpringApplication.run(UniversaltestsoftwareClientApiApplication.class, args);
}
}

View File

@@ -0,0 +1,173 @@
package com.cbsd.universaltestsoftware_client.boardTask;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.cbsd.universaltestsoftware_client.dto.PageChannelDataDto;
import com.cbsd.universaltestsoftware_client.entity.ChannelData;
import com.cbsd.universaltestsoftware_client.entity.DataBoardChannel;
import com.cbsd.universaltestsoftware_client.mapper.ChannelDataMapper;
import com.cbsd.universaltestsoftware_client.mapper.DataBoardChannelMapper;
import com.cbsd.universaltestsoftware_client.parser.model.FiledParseData;
import com.cbsd.universaltestsoftware_client.util.DateUtils;
import com.cbsd.universaltestsoftware_client.vo.ChannelDataVo;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Component
public class PushHolder {
// 使用ConcurrentHashMap存储每个dataBoardId对应的PushSession确保线程安全
private final ConcurrentHashMap<String, PushSession> POOL = new ConcurrentHashMap<>();
@Resource
private DataBoardChannelMapper dataBoardChannelMapper;
@Resource
private ChannelDataMapper channelDataMapper;
// 根据dataBoardId获取对应的PushSession
public PushSession get(String id) {
return POOL.get(id);
}
// 创建一个新的PushSession
public synchronized PushSession create(PageChannelDataDto cmd) {
// 如果已经存在相同的dataBoardId先停止旧的PushSession
stop(cmd.getDataBoardId());
PushSession s = new PushSession();
s.boardId = cmd.getDataBoardId();
s.pageSize = cmd.getPageSize();
s.startTime = cmd.getStartTime();
s.endTime = cmd.getEndTime();
int want = cmd.getPageSize() * 6; // 初始拉取数据条数为pageSize的4倍
cmd.setWant(want);
List<ChannelDataVo> first = getData(cmd); // 获取第一批数据
s.queue.addAll(first.subList(0, Math.min(first.size(), want))); // 将第一批数据加入队列
if (!first.isEmpty()) {
int idx = Math.min(first.size(), want) - 1;
if (idx >= 0) {
long timestamp = first.get(idx).getTimestamp();
s.lastTime = DateUtils.timestampToDateString(timestamp, "yyyy-MM-dd HH:mm:ss.SSS"); // 更新最后时间
}
}
s.worker = new Thread(() -> pullLoop(s), "pull-" + s.boardId); // 创建拉取数据的线程
s.worker.setDaemon(true);
s.worker.start();
POOL.put(s.boardId, s); // 将新的PushSession加入POOL
return s;
}
// 停止指定dataBoardId的PushSession
public synchronized void stop(String boardId) {
PushSession s = POOL.remove(boardId);
if (s != null) s.shutdown(); // 调用shutdown方法停止线程
}
// 更新指定dataBoardId的分页参数
public synchronized void update(PageChannelDataDto cmd) {
PushSession s = POOL.get(cmd.getDataBoardId());
if (s == null) {
create(cmd); // 如果不存在创建一个新的PushSession
return;
}
// 如果startTime或endTime发生变化停止旧的PushSession并创建新的
if (!cmd.getStartTime().equals(s.startTime) || !cmd.getEndTime().equals(s.endTime)) {
s.shutdown();
create(cmd);
} else {
// 如果只有pageSize发生变化直接更新pageSize
s.pageSize = cmd.getPageSize();
}
}
// 拉取数据的循环逻辑
private void pullLoop(PushSession s) {
while (s.isRunning()) {
try {
int want = s.pageSize * 5; // 每次拉取数据条数为pageSize的3倍
if (s.queue.size() < want) {
PageChannelDataDto cmd = new PageChannelDataDto();
cmd.setWant(want);
cmd.setDataBoardId(s.boardId);
cmd.setStartTime(s.startTime);
cmd.setEndTime(s.endTime);
cmd.setLastTime(s.lastTime);
List<ChannelDataVo> chunk = getData(cmd); // 获取一批数据
if (chunk.isEmpty()) {
break; // 如果没有数据,退出循环
}
int gap = want - s.queue.size();
s.queue.addAll(chunk.subList(0, Math.min(chunk.size(), gap))); // 将数据加入队列
long timestamp = chunk.get(Math.min(chunk.size(), gap) - 1).getTimestamp();
s.lastTime = DateUtils.timestampToDateString(timestamp, "yyyy-MM-dd HH:mm:ss.SSS"); // 更新最后时间
}
TimeUnit.SECONDS.sleep(4); // 每5秒拉取一次数据
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}
// 根据PageChannelDataDto获取数据
public List<ChannelDataVo> getData(PageChannelDataDto pageChannelDataDto) {
ArrayList<ChannelDataVo> channelDataVos = new ArrayList<>();
try {
LambdaQueryWrapper<DataBoardChannel> dataBoardChannelLambdaQueryWrapper = new LambdaQueryWrapper<>();
dataBoardChannelLambdaQueryWrapper.eq(DataBoardChannel::getDataBoardId, pageChannelDataDto.getDataBoardId())
.groupBy(DataBoardChannel::getChannelId);
List<DataBoardChannel> dataBoardChannelList = dataBoardChannelMapper.selectList(dataBoardChannelLambdaQueryWrapper);
List<String> channelIds = dataBoardChannelList.stream().map(DataBoardChannel::getChannelId).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(channelIds)) {
LambdaQueryWrapper<ChannelData> channelDataLambdaQueryWrapper = new LambdaQueryWrapper<>();
channelDataLambdaQueryWrapper
.between(StringUtils.isNotBlank(pageChannelDataDto.getStartTime()) && StringUtils.isNotBlank(pageChannelDataDto.getEndTime()), ChannelData::getTime, pageChannelDataDto.getStartTime(), pageChannelDataDto.getEndTime())
.in(ChannelData::getChannelId, channelIds)
.gt(StringUtils.isNotBlank(pageChannelDataDto.getLastTime()), ChannelData::getTime, pageChannelDataDto.getLastTime())
.last("limit " + pageChannelDataDto.getWant())
.orderByAsc(ChannelData::getTime);
List<ChannelData> channelDataList = channelDataMapper.selectList(channelDataLambdaQueryWrapper);
for (ChannelData channelData : channelDataList) {
ArrayList<FiledParseData> filedParseData = new ArrayList<>();
ChannelDataVo parserMessage = new ChannelDataVo();
parserMessage.setChannelId(channelData.getChannelId());
if (StringUtils.isNotBlank(channelData.getData())) {
try {
List<FiledParseData> filedParseDataList = JSON.parseArray(channelData.getData(), FiledParseData.class);
filedParseData.addAll(filedParseDataList);
} catch (Exception e) {
e.printStackTrace();
}
}
parserMessage.setFiledParseDataList(filedParseData);
parserMessage.setTimestamp(convertToTimestamp(channelData.getTime()));
parserMessage.setDataBoardId(pageChannelDataDto.getDataBoardId());
channelDataVos.add(parserMessage);
}
}
}catch (Exception e){
e.printStackTrace();
}
return channelDataVos;
}
// 将时间字符串转换为时间戳
public static long convertToTimestamp(String dateTimeStr) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
LocalDateTime localDateTime = LocalDateTime.parse(dateTimeStr, formatter);
return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
}
}

View File

@@ -0,0 +1,40 @@
package com.cbsd.universaltestsoftware_client.boardTask;
import com.cbsd.universaltestsoftware_client.vo.ChannelDataVo;
import lombok.Data;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
@Data
public class PushSession {
// 用于控制线程是否运行的原子布尔变量
private final AtomicBoolean run = new AtomicBoolean(true);
// 每次拉取的数据条数
volatile int pageSize;
// 上次拉取的最后时间(字符串格式)
volatile String lastTime;
// 数据拉取的开始时间
volatile String startTime;
// 数据拉取的结束时间
volatile String endTime;
// 存储数据的阻塞队列
final LinkedBlockingQueue<ChannelDataVo> queue = new LinkedBlockingQueue<>();
// 数据拉取的线程
Thread worker;
// 数据板ID
String boardId;
// 停止线程的方法
public void shutdown() {
run.set(false); // 设置线程停止标志
if (worker != null) {
worker.interrupt(); // 中断线程
}
}
// 检查线程是否正在运行
public boolean isRunning() {
return run.get();
}
}

View File

@@ -0,0 +1,22 @@
package com.cbsd.universaltestsoftware_client.config;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class BasePage<T> extends Page<T> {
//关键字查询
@ApiModelProperty("关键字查询")
private String keyword;
@ApiModelProperty(name = "开始时间")
private String startTime;
@ApiModelProperty(name = "结束时间")
private String endTime;
}

View File

@@ -0,0 +1,26 @@
package com.cbsd.universaltestsoftware_client.config;
import org.apache.logging.log4j.core.appender.db.jdbc.AbstractConnectionSource;
import org.springframework.util.Assert;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class ConnectionFactory extends AbstractConnectionSource
{
private final DataSource dataSource;
public ConnectionFactory(DataSource dataSource)
{
Assert.notNull(dataSource, "dataSource can not be null");
this.dataSource = dataSource;
}
@Override
public Connection getConnection()
throws SQLException
{
return dataSource.getConnection();
}
}

View File

@@ -0,0 +1,82 @@
package com.cbsd.universaltestsoftware_client.config;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.sql.Types;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @ClassName GeneratorCode
* @Author FY
* @Version 1.0.0
* @Description 代码生成器
* @CreateTime 2023年04月22日 15:49:00
*/
public class
GeneratorCode {
/**
* 数据源配置
*/
private static final DataSourceConfig.Builder DATA_SOURCE_CONFIG = new DataSourceConfig
.Builder("jdbc:mysql://192.168.100.40:3306/universaltestsoftware_client_api?serverTimezone=GMT%2B8&characterEncoding=utf8&useSSL=true&allowMultiQueries=true&serverTimezone=GMT%2B8", "root", "Fushoukeji1234");
/**
* 代码生成器
*
* @param args
*/
public static void main(String[] args) {
FastAutoGenerator.create(DATA_SOURCE_CONFIG)
.globalConfig(builder -> {
builder.author("admin") // 设置作者
.enableSwagger() // 开启 swagger 模式
.disableOpenDir()
.dateType(DateType.ONLY_DATE)
.outputDir("C:\\gs\\project\\universaltestsoftware_client_api\\src\\main\\java"); // 指定输出目录
})
.dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
int typeCode = metaInfo.getJdbcType().TYPE_CODE;
if (typeCode == Types.SMALLINT) {
// 自定义类型转换
return DbColumnType.INTEGER;
}
return typeRegistry.getColumnType(metaInfo);
}))
.packageConfig(builder -> {
builder.entity("entity").parent("com.cbsd.universaltestsoftware_client") // 设置父包名
.pathInfo(Collections.singletonMap(OutputFile.xml, "C:\\gs\\project\\universaltestsoftware_client_api\\src\\main\\resources\\mapper")); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.addInclude(getTables("data_board,data_board_channel")) // 设置需要生成的表名
.addTablePrefix(""); // 设置过滤表前缀
builder.serviceBuilder().formatServiceFileName("%sService");
builder.entityBuilder().logicDeleteColumnName("del").enableFileOverride().idType(IdType.ASSIGN_ID).enableTableFieldAnnotation().enableLombok().disableSerialVersionUID();
builder.mapperBuilder().enableFileOverride().enableBaseResultMap().enableBaseColumnList();
builder.controllerBuilder().enableRestStyle();
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板默认的是Velocity引擎模板
.execute();
}
/**
* 处理多表情况
*
* @param tables 表名
* @return List<String>
*/
protected static List<String> getTables(String tables) {
return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
}
}

View File

@@ -0,0 +1,16 @@
package com.cbsd.universaltestsoftware_client.config;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface IBaseMapper<T> extends BaseMapper<T> {
/**
* 批量插入
* @param batchList 批量数据
* @return insert 数量
*/
int insertBatchSomeColumn(@Param("list") List<T> batchList);
}

View File

@@ -0,0 +1,22 @@
package com.cbsd.universaltestsoftware_client.config;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
import org.apache.ibatis.session.Configuration;
import java.util.List;
/**
* 批量插入 SQL 注入器
*/
public class InsertBatchSqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
methodList.add(new InsertBatchSomeColumn());
return methodList;
}
}

View File

@@ -0,0 +1,62 @@
package com.cbsd.universaltestsoftware_client.config;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.db.ColumnMapping;
import org.apache.logging.log4j.core.appender.db.jdbc.ColumnConfig;
import org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
@Component
public class Log4j2Configuration implements ApplicationListener<ContextRefreshedEvent>
{
private final DataSource dataSource;
public Log4j2Configuration(DataSource dataSource)
{
this.dataSource = dataSource;
}
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent)
{
final LoggerContext ctx = LoggerContext.getContext(false);
final ColumnConfig[] cc =
{ColumnConfig.newBuilder().setConfiguration(ctx.getConfiguration()).setName("event_id").setPattern("%X{id}").setUnicode(false).build(),
ColumnConfig.newBuilder().setConfiguration(ctx.getConfiguration()).setName("event_date").setEventTimestamp(true).setUnicode(false).build(),
ColumnConfig.newBuilder().setConfiguration(ctx.getConfiguration()).setName("thread").setPattern("%t %x").setUnicode(false).build(),
ColumnConfig.newBuilder().setConfiguration(ctx.getConfiguration()).setName("log_class").setPattern("%C").setUnicode(false).build(),
ColumnConfig.newBuilder().setConfiguration(ctx.getConfiguration()).setName("method").setPattern("%M").setUnicode(false).build(),
ColumnConfig.newBuilder().setConfiguration(ctx.getConfiguration()).setName("message").setPattern("%m").setUnicode(false).build(),
ColumnConfig.newBuilder().setConfiguration(ctx.getConfiguration()).setName("exception").setPattern("%ex{full}").setUnicode(false).build(),
ColumnConfig.newBuilder().setConfiguration(ctx.getConfiguration()).setName("level").setPattern("%level").setUnicode(false).build(),
ColumnConfig.newBuilder()
.setConfiguration(ctx.getConfiguration())
.setName("time")
.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS}")
.setUnicode(false)
.build()};
// 配置appender
final Appender appender = JdbcAppender.newBuilder()
.setName("databaseAppender")
.setIgnoreExceptions(false)
.setConnectionSource(new ConnectionFactory(dataSource))
.setTableName("boot_log")
.setColumnConfigs(cc)
.setColumnMappings(new ColumnMapping[0])
.build();
appender.start();
ctx.getConfiguration().addAppender(appender);
// 指定哪些logger输出的日志保存在mysql中
ctx.getConfiguration().getLoggerConfig("com.cbsd").addAppender(appender, Level.INFO, null);
ctx.updateLoggers();
}
}

View File

@@ -0,0 +1,65 @@
package com.cbsd.universaltestsoftware_client.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.cbsd.universaltestsoftware_client.util.YamlUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import javax.sql.DataSource;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public final class LogPoolManager {
private static DataSource dataSource;
private static String configLocation;
private LogPoolManager() {
super();
}
public static void setConfigLocation(String configLocation) {
LogPoolManager.configLocation = configLocation;
}
public static synchronized void init() {
if (dataSource != null) {
return; // 避免重复初始化
}
try {
if (StringUtils.isNotBlank(configLocation)) {
File file = new File(configLocation);
String text = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
Properties props = YamlUtils.yamlToProperties(text);
// 直接实例化DruidDataSource而非通过DataSourceBuilder
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUrl(props.getProperty("spring.datasource.url"));
druidDataSource.setUsername(props.getProperty("spring.datasource.username"));
druidDataSource.setPassword(props.getProperty("spring.datasource.password"));
// 关键禁用SQL解析功能解决ResultSetColumnMetaData错误
druidDataSource.setPoolPreparedStatements(false);
druidDataSource.setFilters("stat"); // 只保留统计功能移除wall等可能引起解析的过滤器
druidDataSource.setProxyFilters(null); // 清空代理过滤器
dataSource = druidDataSource;
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
if (dataSource == null) {
init();
}
Assert.notNull(dataSource, "dataSource can not be null");
return dataSource.getConnection();
}
}

View File

@@ -0,0 +1,41 @@
package com.cbsd.universaltestsoftware_client.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisPlusConfig {
/**
* 分页插件配置
*
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
/**
* 自定义批量插入 SQL 注入器
*/
@Bean
public InsertBatchSqlInjector insertBatchSqlInjector() {
return new InsertBatchSqlInjector();
}
}

View File

@@ -0,0 +1,82 @@
package com.cbsd.universaltestsoftware_client.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@Configuration //表明当前类是配置类
@EnableOpenApi //表示开启生成接口文档功能只有开启了OpenApi,才可以实现生成接口文档的功能)
public class SwaggerConfig {
@Bean
public Docket docket() {
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.cbsd.universaltestsoftware_client.controller"))
.paths(PathSelectors.any())
.build()
.securitySchemes(securitySchemes()) // 添加安全方案
.securityContexts(Collections.singletonList(securityContext())); // 添加上下文
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Swagger3 API文档")
.description("RESTFul 风格接口")
.version("1.0")
.build();
}
private List<SecurityScheme> securitySchemes() {
List<SecurityScheme> apiKeyList = new ArrayList<>();
// 添加sessionId认证
apiKeyList.add(new ApiKey("sessionId", "sessionId", "header"));
// 添加tenantId请求头支持
// apiKeyList.add(new ApiKey("tenantId", "tenantId", "header"));
return apiKeyList;
}
/**
* 设置swagger认证的安全上下文
*/
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(defaultAuth())
.build();
}
/**
* 默认的安全引用包含sessionId和tenantId
*/
private List<SecurityReference> defaultAuth() {
AuthorizationScope[] authorizationScopes = new AuthorizationScope[]{
new AuthorizationScope("web", "All scope is trusted!")
};
return Arrays.asList(
new SecurityReference("sessionId", authorizationScopes)
// new SecurityReference("tenantId", authorizationScopes)
);
}
}

View File

@@ -0,0 +1,339 @@
package com.cbsd.universaltestsoftware_client.controller;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.cbsd.universaltestsoftware_client.dto.FileInfo;
import com.cbsd.universaltestsoftware_client.util.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigInteger;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Api(tags = "文件上传下载相关操作的接口文档")
@RestController()
@RequestMapping("/api/common/backstage/file")
public class BackageFileController {
// 得到一个用来记录日志的对象,这样在打印信息时能够标记打印的是哪个类的信息
private static final Log logger = LogFactory.getLog(BackageFileController.class);
@Value("${cbsd.uploadfilesrootpath}")
private String uploadfilesrootpath;
/**
* 单文件上传
*/
@ApiOperation(value = "单个文件上传", notes = "")
@PostMapping("/fileupload")
public Result<FileInfo> oneFileUpload(MultipartFile file) {
if (file == null) {
return Result.error(ResultCode.PARAMETER_ERROR, "file文件参数未传");
}
String fileName = file.getOriginalFilename();
if (StringUtils.isBlank(fileName)) {
return Result.error("文件上传失败,请检查文件名称");
}
try {
String suffix = fileName.substring(fileName.lastIndexOf("."));
String fileId = UUIDUtils.getUUID();
String parentDic = DateUtils.dateToString("yyyy/MM/dd");
String filePath = parentDic + "/" + fileId + suffix;
//创建文件夹
File parentFile = new File(uploadfilesrootpath, parentDic);
if (!parentFile.exists()) {
parentFile.mkdirs();
}
Path savePath = Paths.get(uploadfilesrootpath, filePath);
Files.write(savePath, file.getBytes());
FileInfo fileInfo = new FileInfo();
fileInfo.setNewFileName(fileId + suffix);
fileInfo.setOriginalFilename(fileName);
fileInfo.setRelativePath(parentDic);
fileInfo.setNginxFileReadPath(filePath);
fileInfo.setFileSize(String.valueOf(file.getSize()));
return Result.success(fileInfo);
} catch (Exception e) {
e.printStackTrace();
}
return Result.error("文件上传失败");
}
@ApiOperation(value = "多个文件上传", notes = "上传文件参数名称统一files,"
+ "如果中途有个别文件上传没有成功,将不会返回错误,只会返回对应正确上传文件信息列表,"
+ "前端请注意查看对比数量")
@PostMapping("/multifile") //ApiResultResponse<List<FileInfo>>
public Result<List<FileInfo>> multiFileUpload(List<MultipartFile> files) {
if (files == null || files.isEmpty()) {
return Result.error("文件不能为空");
}
List<FileInfo> fileInfoList = new ArrayList<FileInfo>();
for (MultipartFile file : files) {
Result<FileInfo> result = oneFileUpload(file);
if (result.getCode() == ResultCode.OK && result.getData() != null) {
fileInfoList.add(result.getData());
}
}
return Result.success(fileInfoList);
}
/**
* 执行下载
*/
@ApiOperation(value = "文件下载")
@GetMapping("download") //ApiResultResponse<String>
public ResponseEntity<Resource> download(@RequestParam String filePath, @RequestParam(required = false) String fileName) throws Exception {
if (StringUtils.isBlank(filePath)) {
return null;
}
String downloadPath = uploadfilesrootpath + filePath;
File downloadFile = new File(downloadPath);
HttpHeaders headers = new HttpHeaders();
//下载
headers.add("Content-Disposition", "attachment; filename=" + downloadFile.getName());
//二进制流
String mediaType = "application/octet-stream";
return ResponseEntity.ok()
.headers(headers)
.contentLength(downloadFile.length())
.contentType(MediaType.parseMediaType(mediaType))
.body(new FileSystemResource(downloadFile));
}
@ApiOperation(value = "文件下载或预览", httpMethod = "GET", notes = "文件下载或预览")
@ApiImplicitParams({
@ApiImplicitParam(name = "filePath", value = "文件路劲", dataType = "String", dataTypeClass = String.class, paramType = "query"),
@ApiImplicitParam(name = "downloadOrRead", value = "下载或预览 download/read", dataType = "String", dataTypeClass = String.class, paramType = "query")
})
@RequestMapping("/fileDownLoad")
public ResponseEntity<Resource> fileDownLoad(
@RequestParam String filePath,
@RequestParam(required = false) String fileName,
@RequestParam(required = false) String downloadOrRead) throws UnsupportedEncodingException {
if (StringUtils.isBlank(filePath)) {
return ResponseEntity.badRequest().build();
}
String downloadPath = uploadfilesrootpath + filePath;
File downloadFile = new File(downloadPath);
if (!downloadFile.exists()) {
return ResponseEntity.notFound().build();
}
String originalFileName = downloadFile.getName();
String actualFileName = StringUtils.isNotBlank(fileName) ? fileName : originalFileName;
// 如果用户传了文件名,但没有后缀,就补上原始后缀
if (StringUtils.isNotBlank(fileName) && !fileName.contains(".")) {
String suffix = originalFileName.substring(originalFileName.lastIndexOf("."));
actualFileName = fileName + suffix;
}
// URL 编码文件名(防止中文乱码)
actualFileName = URLEncoder.encode(actualFileName, StandardCharsets.UTF_8.toString())
.replaceAll("\\+", "%20");
HttpHeaders headers = new HttpHeaders();
String mediaType;
if ("read".equals(downloadOrRead)) {
// 预览
headers.add(HttpHeaders.CONTENT_DISPOSITION, "inline; filename*=UTF-8''" + actualFileName);
String suffix = originalFileName.substring(originalFileName.lastIndexOf("."));
mediaType = MediaTypeUtils.getMediaType(suffix); // 你需要实现这个工具类
} else {
// 下载
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + actualFileName);
mediaType = "application/octet-stream";
}
return ResponseEntity.ok()
.headers(headers)
.contentLength(downloadFile.length())
.contentType(MediaType.parseMediaType(mediaType))
.body(new FileSystemResource(downloadFile));
}
@GetMapping("/getVideo")
public void getVideo(HttpServletResponse response, String filePath, HttpServletRequest request) throws FileNotFoundException {
// InputStream objectContent = OssUtils.ossGetInputStream( url) ;
// InputStream objectContent = new FileInputStream("/Users/chenlin/Downloads/123.mp4");
String url = uploadfilesrootpath + filePath;
System.err.println(url);
try {
File tempFile = new File(url);
RandomAccessFile randomFile = new RandomAccessFile(tempFile, "r");//只读模式
long contentLength = randomFile.length();
String range = request.getHeader("Range");
int start = 0, end = 0;
if (range != null && range.startsWith("bytes=")) {
String[] values = range.split("=")[1].split("-");
start = Integer.parseInt(values[0]);
if (values.length > 1) {
end = Integer.parseInt(values[1]);
}
}
int requestSize = 0;
if (end != 0 && end > start) {
requestSize = end - start + 1;
} else {
requestSize = Integer.MAX_VALUE;
}
byte[] buffer = new byte[2048];
response.setContentType("video/mp4");
response.setHeader("Accept-Ranges", "bytes");
String fileNameString = filePath.substring(filePath.lastIndexOf("/") + 1);
response.setHeader("ETag", fileNameString);
response.setHeader("Last-Modified", new Date().toString());
//第一次请求只返回content length来让客户端请求多次实际数据
if (range == null) {
response.setHeader("Content-length", contentLength + "");
} else {
//以后的多次以断点续传的方式来返回视频数据
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);//206
long requestStart = 0, requestEnd = 0;
String[] ranges = range.split("=");
if (ranges.length > 1) {
String[] rangeDatas = ranges[1].split("-");
requestStart = Integer.parseInt(rangeDatas[0]);
if (rangeDatas.length > 1) {
requestEnd = Integer.parseInt(rangeDatas[1]);
}
}
long length = 0;
if (requestEnd > 0) {
length = requestEnd - requestStart + 1;
response.setHeader("Content-length", "" + length);
response.setHeader("Content-Range", "bytes " + requestStart + "-" + requestEnd + "/" + contentLength);
} else {
length = contentLength - requestStart;
response.setHeader("Content-length", "" + length);
response.setHeader("Content-Range", "bytes " + requestStart + "-" + (contentLength - 1) + "/" + contentLength);
}
}
ServletOutputStream out = response.getOutputStream();
int needSize = requestSize;
randomFile.seek(start);
while (needSize > 0) {
int len = randomFile.read(buffer);
if (needSize < buffer.length) {
out.write(buffer, 0, needSize);
} else {
out.write(buffer, 0, len);
if (len < buffer.length) {
break;
}
}
needSize -= buffer.length;
}
randomFile.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 下载保存时中文文件名的字符编码转换方法
*/
public String toUTF8String(String str) {
StringBuffer sb = new StringBuffer();
int len = str.length();
for (int i = 0; i < len; i++) {
// 取出字符中的每个字符
char c = str.charAt(i);
// Unicode码值为0~255时不做处理
if (c >= 0 && c <= 255) {
sb.append(c);
} else { // 转换 UTF-8 编码
byte b[];
try {
b = Character.toString(c).getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
b = null;
}
// 转换为%HH的字符串形式
for (int j = 0; j < b.length; j++) {
int k = b[j];
if (k < 0) {
k &= 255;
}
sb.append("%" + Integer.toHexString(k).toUpperCase());
}
}
}
return sb.toString();
}
/**
* 获取上传文件的md5
*
* @param file
* @return
* @throws IOException
*/
public String getMd5(MultipartFile file) {
try {
//获取文件的byte信息
byte[] uploadBytes = file.getBytes();
// 拿到一个MD5转换器
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] digest = md5.digest(uploadBytes);
//转换为16进制
return new BigInteger(1, digest).toString(16);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 验证文件信息是否是 相关路径下的文件数据
*
* @param relativeUrl 放开的相关路径
* @param filePathUrl 下载文件路径
* @return
*/
public static boolean isPathSafe(String relativeUrl, String filePathUrl) {
Path basePath = Paths.get(relativeUrl);
Path pathToCheck = Paths.get(filePathUrl);
return basePath.resolve(pathToCheck.normalize()).normalize().startsWith(basePath);
}
}

View File

@@ -0,0 +1,102 @@
package com.cbsd.universaltestsoftware_client.controller;
import com.cbsd.universaltestsoftware_client.dto.BoardTemperatureDto;
import com.cbsd.universaltestsoftware_client.dto.ChannelPageDto;
import com.cbsd.universaltestsoftware_client.dto.PageBoard;
import com.cbsd.universaltestsoftware_client.entity.Board;
import com.cbsd.universaltestsoftware_client.entity.Channel;
import com.cbsd.universaltestsoftware_client.service.BoardService;
import com.cbsd.universaltestsoftware_client.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Parameter;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
/**
* <p>
* 板卡 前端控制器
* </p>
*
* @author admin
* @since 2025-08-26
*/
@RestController
@Api(tags = "板卡端接口")
@RequestMapping("/api/board")
public class BoardController {
@Resource
private BoardService boardService;
@ApiOperation("获取板卡列表")
@PostMapping("/pageBoardList")
public String pageList(@RequestBody @Validated PageBoard pageBoard) {
return boardService.pageList(pageBoard);
}
@ApiOperation("添加修改板卡")
@PostMapping("/saveOrUpdateBoard")
public String saveOrUpdateBoard(@RequestBody @Validated Board board) {
return boardService.saveOrUpdateBoard(board);
}
@ApiOperation("删除板卡")
@GetMapping("/deleteBoardById")
public String deleteById(@RequestParam String serverId, @RequestParam String boardId) {
return boardService.deleteById(serverId, boardId);
}
@ApiOperation("获取板卡类型")
@GetMapping("/getBoardType")
public String getBoardType(@RequestParam String serverId) {
return boardService.getBoardType(serverId);
}
@ApiOperation("新增或者修改通道")
@PostMapping("/saveOrUpdateChannel")
public String saveOrUpdateChannel(@RequestBody @Validated Channel channel) {
return boardService.saveOrUpdateChannel(channel);
}
@ApiOperation("获取通道列表")
@PostMapping("/pageChannelList")
public Result pageChannelList(@RequestBody @Validated ChannelPageDto channelPageDto) {
return boardService.pageChannelList(channelPageDto);
}
@ApiOperation("获取所有通道类型")
@GetMapping("/getChannelTypeAll")
public String getChannelTypeAll(@RequestParam String serverId, @Parameter(description = "boardTypeId") @NotNull(message = "板卡类型id不可以为空") String boardTypeId) {
return boardService.getChannelTypeAll(serverId, boardTypeId);
}
@ApiOperation("删除通道")
@GetMapping("/deleteChannelById")
public String deleteChannelById(@RequestParam String serverId, @RequestParam String channelId) {
return boardService.deleteChannelById(serverId, channelId);
}
@ApiOperation("根据版卡id获取通道的路径")
@GetMapping("/getChannelPath")
public String getChannelPath(@RequestParam String serverId, @RequestParam String boardId) {
return boardService.getChannelPath(serverId, boardId);
}
@ApiOperation("刷新绑卡信息")
@GetMapping("/refressBoardInformation")
public String refressBoardInformation(@RequestParam String serverId) {
return boardService.refressBoardInformation(serverId);
}
@ApiOperation("获取板卡温度")
@PostMapping("/getBoardTemperature")
public String getBoardTemperature(@RequestBody BoardTemperatureDto dto) {
return boardService.getBoardTemperature(dto);
}
}

View File

@@ -0,0 +1,50 @@
package com.cbsd.universaltestsoftware_client.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cbsd.universaltestsoftware_client.dto.BootLogDeleteDto;
import com.cbsd.universaltestsoftware_client.dto.BootLogPageDto;
import com.cbsd.universaltestsoftware_client.entity.BootLog;
import com.cbsd.universaltestsoftware_client.service.IBootLogService;
import com.cbsd.universaltestsoftware_client.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* <p>
* 前端控制器
* </p>
*
* @author wt
* @since 2025-09-03
*/
@RestController
@Api(tags = "日志记录")
@RequestMapping("/api/boot-log")
public class BootLogController {
@Resource
private IBootLogService bootLogService;
@ApiOperation(value = "日志记录-查询分页")
@PostMapping("/bootLogPage")
public Result<Page<BootLog>> bootLogPage(@RequestBody @Validated BootLogPageDto bootLogPageDto) {
return bootLogService.bootLogPage(bootLogPageDto);
}
@ApiOperation(value = "日志记录-删除分页")
@PostMapping("/bootLogDelete")
public Result<String> bootLogDelete(@RequestBody @Validated BootLogDeleteDto bootLogDeleteDto) {
return bootLogService.bootLogDelete(bootLogDeleteDto);
}
}

View File

@@ -0,0 +1,83 @@
package com.cbsd.universaltestsoftware_client.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cbsd.universaltestsoftware_client.dto.ChannelDataDto;
import com.cbsd.universaltestsoftware_client.dto.ChannelDataHistoryDto;
import com.cbsd.universaltestsoftware_client.dto.ChannelDataStatisticsDto;
import com.cbsd.universaltestsoftware_client.dto.PageChannelDataDto;
import com.cbsd.universaltestsoftware_client.entity.ChannelDataHistory;
import com.cbsd.universaltestsoftware_client.parser.model.FiledParseData;
import com.cbsd.universaltestsoftware_client.service.ChannelDataService;
import com.cbsd.universaltestsoftware_client.util.Result;
import com.cbsd.universaltestsoftware_client.vo.ChannelDataStatisticsVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
import java.util.List;
@RestController
@Api(tags = "数据回访")
@RequestMapping("/api/channelData")
public class ChannelDataController {
@Resource
private ChannelDataService channelDataService;
@PostConstruct
public void init(){
channelDataService.clearChannelData();
}
@ApiOperation("开始数据拉取")
@PostMapping("/start")
public Result<String> start(@RequestBody @Validated PageChannelDataDto pageChannelDataDto) throws Exception {
// 调用服务层的start方法开始数据拉取
channelDataService.start(pageChannelDataDto);
return Result.success();
}
@ApiOperation("停止数据拉取")
@GetMapping("/stop")
public Result<Void> stop(@NotBlank @RequestParam String dataBoardId) {
// 调用服务层的stop方法停止指定dataBoardId的数据拉取
channelDataService.stop(dataBoardId);
return Result.success();
}
@ApiOperation("更新分页参数")
@PostMapping("/updateData")
public Result<String> updateData(@RequestBody @Validated PageChannelDataDto pageChannelDataDto) {
// 调用服务层的update方法更新分页参数
channelDataService.updateData(pageChannelDataDto);
return Result.success();
}
@ApiOperation(value = "通道历史数据-查询分页")
@PostMapping("/channelDataQuery")
public String channelDataQuery(@RequestBody @Validated ChannelDataHistoryDto channelDataHistoryDto) {
return channelDataService.channelDataQuery(channelDataHistoryDto);
}
@ApiOperation(value = "通道历史数据-删除")
@PostMapping("/channelDataDelete")
public String channelDataDelete(@RequestBody @Validated ChannelDataHistoryDto channelDataHistoryDto) {
return channelDataService.channelDataDelete(channelDataHistoryDto);
}
@ApiOperation(value = "通道数据统计")
@PostMapping("/getChannelDataStatistics")
public Result<List<ChannelDataStatisticsVo>> getChannelDataStatistics(@RequestBody ChannelDataStatisticsDto dto) {
return channelDataService.getChannelDataStatistics(dto);
}
@ApiOperation(value = "清除通道数据统计")
@PostMapping("/clearChannelDataStatistics")
public Result<Integer> clearChannelDataStatistics(@RequestBody ChannelDataStatisticsDto dto) {
return channelDataService.clearChannelDataStatistics(dto);
}
}

View File

@@ -0,0 +1,18 @@
package com.cbsd.universaltestsoftware_client.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 前端控制器
* </p>
*
* @author admin
* @since 2025-09-10
*/
@RestController
@RequestMapping("/dataBoardChannel")
public class DataBoardChannelController {
}

View File

@@ -0,0 +1,161 @@
package com.cbsd.universaltestsoftware_client.controller;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cbsd.universaltestsoftware_client.dto.DataClearDto;
import com.cbsd.universaltestsoftware_client.dto.DownloadDto;
import com.cbsd.universaltestsoftware_client.dto.ExportDataBoardDto;
import com.cbsd.universaltestsoftware_client.dto.InsertDataBoardDto;
import com.cbsd.universaltestsoftware_client.entity.DataBoard;
import com.cbsd.universaltestsoftware_client.entity.DataBoardChannel;
import com.cbsd.universaltestsoftware_client.entity.Download;
import com.cbsd.universaltestsoftware_client.service.DataBoardService;
import com.cbsd.universaltestsoftware_client.service.SystemConfigService;
import com.cbsd.universaltestsoftware_client.util.MediaTypeUtils;
import com.cbsd.universaltestsoftware_client.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* <p>
* 数据看板 前端控制器
* </p>
*
* @author admin
* @since 2025-09-10
*/
@RestController
@Api(tags = "数据看板")
@RequestMapping("/api/dataBoard")
public class DataBoardController {
@Resource
private DataBoardService dataBoardService;
@Value("${cbsd.downloadUrl}")
private String downloadDir;
@ApiOperation("新增修改数据看板")
@PostMapping("/saveOrUpdateDataBoard")
public Result<Void> saveOrUpdateDataBoard(@RequestBody @Validated InsertDataBoardDto insertDataBoardDto) throws Exception {
dataBoardService.saveOrUpdateDataBoard(insertDataBoardDto);
return Result.success();
}
@ApiOperation("删除数据看板")
@GetMapping("/removeDataBoardById")
public Result<Void> removeDataBoardById(@RequestParam String dataBoardId) throws Exception {
dataBoardService.removeDataBoardById(dataBoardId);
return Result.success();
}
@ApiOperation("查询数据看板")
@GetMapping("/listDataBoard")
public Result<List<DataBoard>> listDataBoard(@RequestParam Integer dataType) throws Exception {
return Result.success(dataBoardService.listDataBoard(dataType));
}
@ApiOperation("通过id修改颜色或者左轴")
@PostMapping("/updateDataBoardById")
public Result<Void> updateDataBoardById(@RequestBody DataBoardChannel dataBoardChannel) throws Exception {
dataBoardService.updateDataBoardById(dataBoardChannel);
return Result.success();
}
@ApiOperation("导出数据回访")
@PostMapping("/exportDataBoard")
public Result<Void> exportDataBoard(@RequestBody @Validated ExportDataBoardDto exportDataBoardDto, HttpServletResponse response) throws Exception {
return dataBoardService.exportDataBoard(exportDataBoardDto, response);
}
@ApiOperation("清除")
@PostMapping("/clear")
public Result<Void> clear(@RequestBody @Validated ExportDataBoardDto exportDataBoardDto) throws Exception {
dataBoardService.clear(exportDataBoardDto);
return Result.success();
}
@ApiOperation("导出历史查看")
@PostMapping("/exportHistory")
public Result<Page<Download>> exportHistory(@RequestBody @Validated DownloadDto downloadDto) {
return dataBoardService.exportHistory(downloadDto);
}
@ApiOperation(value = "文件下载或预览", httpMethod = "GET", notes = "文件下载或预览")
@ApiImplicitParams({
@ApiImplicitParam(name = "filePath", value = "文件路劲", dataType = "String", dataTypeClass = String.class, paramType = "query"),
@ApiImplicitParam(name = "downloadOrRead", value = "下载或预览 download/read", dataType = "String", dataTypeClass = String.class, paramType = "query")
})
@RequestMapping("/fileDownLoad")
public ResponseEntity<org.springframework.core.io.Resource> fileDownLoad(
@RequestParam String filePath,
@RequestParam(required = false) String fileName,
@RequestParam(required = false) String downloadOrRead) throws UnsupportedEncodingException {
if (StringUtils.isBlank(filePath)) {
return ResponseEntity.badRequest().build();
}
String downloadPath = downloadDir + "/"+filePath;
File downloadFile = new File(downloadPath);
if (!downloadFile.exists()) {
return ResponseEntity.notFound().build();
}
String originalFileName = downloadFile.getName();
String actualFileName = StringUtils.isNotBlank(fileName) ? fileName : originalFileName;
// 如果用户传了文件名,但没有后缀,就补上原始后缀
if (StringUtils.isNotBlank(fileName) && !fileName.contains(".")) {
String suffix = originalFileName.substring(originalFileName.lastIndexOf("."));
actualFileName = fileName + suffix;
}
// URL 编码文件名(防止中文乱码)
actualFileName = URLEncoder.encode(actualFileName, StandardCharsets.UTF_8.toString())
.replaceAll("\\+", "%20");
HttpHeaders headers = new HttpHeaders();
String mediaType;
if ("read".equals(downloadOrRead)) {
// 预览
headers.add(HttpHeaders.CONTENT_DISPOSITION, "inline; filename*=UTF-8''" + actualFileName);
String suffix = originalFileName.substring(originalFileName.lastIndexOf("."));
mediaType = MediaTypeUtils.getMediaType(suffix); // 你需要实现这个工具类
} else {
// 下载
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + actualFileName);
mediaType = "application/octet-stream";
}
return ResponseEntity.ok()
.headers(headers)
.contentLength(downloadFile.length())
.contentType(MediaType.parseMediaType(mediaType))
.body(new FileSystemResource(downloadFile));
}
}

View File

@@ -0,0 +1,18 @@
package com.cbsd.universaltestsoftware_client.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 前端控制器
* </p>
*
* @author admin
* @since 2026-02-03
*/
@RestController
@RequestMapping("/download")
public class DownloadController {
}

View File

@@ -0,0 +1,224 @@
package com.cbsd.universaltestsoftware_client.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cbsd.universaltestsoftware_client.dto.*;
import com.cbsd.universaltestsoftware_client.entity.Instruct;
import com.cbsd.universaltestsoftware_client.parser.model.Filed;
import com.cbsd.universaltestsoftware_client.service.InstructService;
import com.cbsd.universaltestsoftware_client.util.CalcUtils;
import com.cbsd.universaltestsoftware_client.util.DataUtils;
import com.cbsd.universaltestsoftware_client.util.ModbusCRC16Utils;
import com.cbsd.universaltestsoftware_client.util.Result;
import com.cbsd.universaltestsoftware_client.vo.ServerListVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.security.NoSuchAlgorithmException;
import java.util.List;
/**
* <p>
* 前端控制器
* </p>
*
* @author admin
* @since 2025-09-01
*/
@RestController
@Api(tags = "指令")
@RequestMapping("/api/instruct")
public class InstructController {
@Resource
private InstructService instructService;
@ApiOperation("获取指令列表")
@PostMapping("/pageInstructList")
public Result<Page<Instruct>> pageList(@RequestBody @Validated InstructPageDto instructPageDto) {
return Result.success(instructService.pageList(instructPageDto));
}
@ApiOperation("修改指令")
@PostMapping("/saveOrUpdateInstruct")
public Result<String> saveOrUpdateInstruct(@RequestBody @Validated Instruct instruct) {
return instructService.saveOrUpdateInstruct(instruct);
}
@ApiOperation("删除指令")
@PostMapping("/deleteInstructById")
public Result<String> deleteInstructById(@RequestBody InstructDeleteDto dto) {
return instructService.deleteInstructById(dto);
}
@ApiOperation("执行指令")
@GetMapping("/execute")
public Result<String> execute(@RequestParam String instructId) {
// return instructService.execute(instructId, null);
return null;
}
@ApiOperation("获取通道列表")
@GetMapping("/getChannelList")
public Result<List<ServerListVo>> getChannelList(String keyword) {
return instructService.getChannelList(keyword);
}
@ApiOperation("获取板载驱动程序注册函数")
@GetMapping("/getChannelFunctionName")
public String getChannelFunctionName(@RequestParam String channelId, @RequestParam String serverId) {
return instructService.getChannelFunctionName(channelId, serverId);
}
@ApiOperation("获取板载驱动额外数据")
@GetMapping("/getBoardDriverExtraData")
public String getBoardDriverExtraData(@RequestParam String channelId, @RequestParam String serverId) {
return instructService.getBoardDriverExtraData(channelId, serverId);
}
@ApiOperation("新增")
@PostMapping("/saveOrUpdateInstructGroup")
public Result<String> saveOrUpdateInstructGroup(@RequestBody @Validated InstructGroupDto instructGroupDto) {
return instructService.saveOrUpdateInstructGroup(instructGroupDto);
}
@ApiOperation("上移")
@GetMapping("/moveUp")
public Result<String> moveUp(@RequestParam String instructId) {
return instructService.moveUp(instructId);
}
@ApiOperation("下移")
@GetMapping("/moveDown")
public Result<String> moveDown(@RequestParam String instructId) {
return instructService.moveDown(instructId);
}
@ApiOperation("根据指令id获取协议参数")
@GetMapping("/getInstructProtocolParam")
public Result<List<Filed>> getInstructProtocolParam(@RequestParam String instructId) {
return instructService.getInstructProtocolParam(instructId);
}
/**
* 至少 2 个常规指令 → 新建组并归组
*/
@ApiOperation("新建指令组:至少 2 个常规指令 → 新建组并归组")
@PostMapping("/createGroupFromList")
public Result<Void> createGroupFromList(@Valid @RequestBody CreateGroupDTO dto) {
instructService.createGroupFromList(dto);
return Result.success();
}
@ApiOperation("批量修改指令参数")
@PostMapping("/batchChangeParam")
public Result<String> batchChangeParam(@RequestBody BatchChangeInstructParamDto dto) {
return instructService.batchChangeParam(dto);
}
@ApiOperation("批量复制")
@PostMapping("/batchCopyBelow")
public Result<Void> batchCopyBelow(@RequestBody @Validated BatchCopyBelowDTO dto) {
instructService.batchCopyBelow(dto);
return Result.success();
}
@ApiOperation("批量移动")
@PostMapping("/batchMoveBelow")
public Result<Void> batchMoveBelow(@RequestBody @Validated BatchMoveBelowDTO dto) {
instructService.batchMoveBelow(dto);
return Result.success();
}
@ApiOperation("上传指令文件")
@PostMapping("/uploadCommandFile")
public Result<String> uploadCommandFile(@RequestParam String instructId, MultipartFile file) {
return instructService.uploadCommandFile(instructId, file);
}
@ApiOperation("删除指令脚本文件")
@PostMapping("/deleteInstructFile")
public Result<String> deleteInstructFile(@RequestBody InstructDeleteFileDto dto) {
return instructService.deleteInstructFile(dto);
}
@ApiOperation("获取指令校验位")
@PostMapping("/instructCalc")
public Result<String> instructCalc(@RequestBody InstructCalcDto dto) {
if (dto == null) {
return Result.error("参数不能为空");
}
if (StringUtils.isBlank(dto.getData())) {
return Result.error("数据不能为空");
}
if (dto.getCalcMethod() == null) {
return Result.error("校验方法不能为空");
}
String calcResult;
if (dto.getCalcMethod() == 1) {
// crc16
calcResult = ModbusCRC16Utils.calculateCRCToHexString(
DataUtils.HexToByteArr(dto.getData()));
} else if (dto.getCalcMethod() == 2) {
// crc32
long result = CalcUtils.crc32Checksum(
DataUtils.HexToByteArr(dto.getData()));
calcResult = Long.toHexString(result).toUpperCase();
} else if (dto.getCalcMethod() == 3) {
// 奇偶校验
byte result = CalcUtils.parityCheck(
DataUtils.HexToByteArr(dto.getData()));
calcResult = Integer.toHexString(result).toUpperCase();
} else if (dto.getCalcMethod() == 4) {
// 校验和
int result = CalcUtils.simpleChecksum(
DataUtils.HexToByteArr(dto.getData()));
calcResult = Integer.toHexString(result).toUpperCase();
} else if (dto.getCalcMethod() == 5) {
// MD5
try {
calcResult = CalcUtils.md5Checksum(
DataUtils.HexToByteArr(dto.getData())).toUpperCase();
} catch (NoSuchAlgorithmException e) {
return Result.error("计算失败");
}
} else if (dto.getCalcMethod() == 6) {
// SHA-256
try {
calcResult = CalcUtils.sha256Checksum(
DataUtils.HexToByteArr(dto.getData())).toUpperCase();
} catch (NoSuchAlgorithmException e) {
return Result.error("计算失败");
}
} else if (dto.getCalcMethod() == 7) {
// 单字节异或校验
try {
calcResult = CalcUtils.byteXOR(dto.getData()).toUpperCase();
} catch (Exception e) {
return Result.error("计算失败");
}
} else {
return Result.error("不支持的校验方式");
}
// ====== 根据 byteCount 截取或补齐 ======
calcResult = CalcUtils.fitToByteCount(calcResult, dto.getByteCount());
return Result.success(calcResult);
}
@ApiOperation("获取指令数据注释")
@GetMapping("/getInstructDataRemark")
public String getInstructDataRemark(@RequestParam String instructId) {
return instructService.getInstructDataRemark(instructId);
}
}

View File

@@ -0,0 +1,93 @@
package com.cbsd.universaltestsoftware_client.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cbsd.universaltestsoftware_client.dto.InvocationPageDto;
import com.cbsd.universaltestsoftware_client.dto.InvocationSortDto;
import com.cbsd.universaltestsoftware_client.entity.Invocation;
import com.cbsd.universaltestsoftware_client.service.InvocationService;
import com.cbsd.universaltestsoftware_client.util.DateUtils;
import com.cbsd.universaltestsoftware_client.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* <p>
* 用列 前端控制器
* </p>
*
* @author admin
* @since 2025-09-01
*/
@RestController
@Api(tags = "用列")
@RequestMapping("/api/invocation")
public class InvocationController {
@Resource
private InvocationService invocationService;
@ApiOperation("获取用列列表")
@PostMapping("/pageList")
public Result<Page<Invocation>> pageList(@RequestBody @Validated InvocationPageDto invocationPageDto) {
return Result.success(invocationService.pageList(invocationPageDto));
}
@ApiOperation("添加或者修改用列")
@PostMapping("/saveOrUpdate")
public Result<String> saveOrUpdate(@RequestBody @Validated Invocation invocation) {
if (StringUtils.isNotBlank(invocation.getInvocationId())) {
invocation.setUpdateTime(DateUtils.dateToString());
} else {
long schemeInvocationCount = invocationService.count(new LambdaQueryWrapper<Invocation>().eq(Invocation::getSchemeId, invocation.getSchemeId()));
invocation.setSort((int) (schemeInvocationCount + 1));
invocation.setCreateTime(DateUtils.dateToString());
}
try {
return invocationService.saveOrUpdate(invocation) ? Result.success("保存成功") : Result.error("保存失败");
} catch (Exception e) {
if (e instanceof DuplicateKeyException) {
return Result.error("同一方案内用例名字重复");
}
return Result.error("保存失败");
}
}
@ApiOperation("删除用列")
@GetMapping("/deleteById")
public Result<String> deleteById(@RequestParam String invocationId) {
return invocationService.deleteById(invocationId);
}
@ApiOperation("排序")
@PostMapping("/sort")
public Result<String> sort(@RequestBody InvocationSortDto dto){
return invocationService.sort(dto);
}
@ApiOperation("用列导出")
@GetMapping("/exportInvocation")
public Result<Void> exportInvocation(@RequestParam String invocationId, HttpServletResponse response)throws IOException {
invocationService.exportInvocation(invocationId, response);
return Result.success();
}
/**
* 导入 XML 文件
*/
@PostMapping("/importXml")
public Result<Void> importXml(@RequestParam("file") MultipartFile file,@RequestParam("schemeId")String schemeId) throws Exception {
invocationService.importXml(file,schemeId);
return Result.success();
}
}

View File

@@ -0,0 +1,100 @@
package com.cbsd.universaltestsoftware_client.controller;
import com.cbsd.client.Test;
import com.cbsd.universaltestsoftware_client.DynamicClassBootstrap;
import com.cbsd.universaltestsoftware_client.dto.SubmitAndCompile;
import com.cbsd.universaltestsoftware_client.util.Result;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.cbsd.universaltestsoftware_client.service.JavaCompileService;
@RestController
@RequestMapping("/api/javaCompiler")
public class JavaCompilerController {
private final JavaCompileService javaCompileService;
@Autowired
public JavaCompilerController(JavaCompileService javaCompileService) {
this.javaCompileService = javaCompileService;
}
/**
* 上传Java文件并编译
*/
@ApiModelProperty("上传Java文件并编译")
@PostMapping("/uploadCompile")
public Result<String> uploadAndCompile(@RequestParam("file") MultipartFile file) {
// 验证文件
if (file.isEmpty()) {
return Result.error("请上传有效的Java文件");
}
String fileName = file.getOriginalFilename();
if (fileName == null || !fileName.endsWith(".java")) {
return Result.error("请上传扩展名为.java的文件");
}
try {
Result<String> stringResult = javaCompileService.compileJavaFile(file);
return stringResult;
} catch (Exception e) {
return Result.error("编译过程出错"+e.getMessage());
}
}
/**
* 提交Java代码字符串并编译
*/
@ApiOperation("提交Java代码字符串并编译")
@PostMapping("/submitCompile")
public Result<String> submitAndCompile(@RequestBody @Validated SubmitAndCompile submitAndCompile) {
if (submitAndCompile.getClassName() == null || submitAndCompile.getClassName().trim().isEmpty()) {
return Result.error("类名不能为空");
}
if (submitAndCompile.getCode() == null || submitAndCompile.getCode().trim().isEmpty()) {
return Result.error("Java代码不能为空");
}
try {
Result<String> stringResult = javaCompileService.compileJavaCode(submitAndCompile.getClassName(), submitAndCompile.getCode());
return stringResult;
} catch (Exception e) {
return Result.error("编译过程出错"+e.getMessage());
}
}
@ApiOperation("获取所有已编译的类")
@GetMapping("/getClasses")
public Result getAllCompiledClasses() {
return Result.success(DynamicClassBootstrap.CLAZZ_CACHE);
}
@ApiOperation("测试执行其中一个clss结果")
@GetMapping("/testExecuteClass")
public Result testExecuteClass(@RequestParam("className") String className) {
Class<?> aClass = DynamicClassBootstrap.CLAZZ_CACHE.get(className);
if (aClass != null) {
try {
Test o = (Test) aClass.newInstance();
return Result.success(o.test());
} catch (Exception e) {
e.printStackTrace();
}
}
return Result.success();
}
}

View File

@@ -0,0 +1,78 @@
package com.cbsd.universaltestsoftware_client.controller;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.cbsd.universaltestsoftware_client.dto.BootLogDeleteDto;
import com.cbsd.universaltestsoftware_client.dto.PageLogDto;
import com.cbsd.universaltestsoftware_client.entity.ServerInfo;
import com.cbsd.universaltestsoftware_client.mapper.ServerMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController
@Api(tags = "服务端日志")
@RequestMapping("/api/log")
public class LogController {
@Resource
private ServerMapper serverMapper;
@ApiOperation("通过服务端id获取日志")
@PostMapping("/getLogList")
public String getLogList(@RequestBody @Validated PageLogDto pageLogDto) {
ServerInfo serverInfo = serverMapper.selectById(pageLogDto.getServerId());
if (serverInfo==null){
throw new RuntimeException("服务端不存在");
}
try {
String url = "http://"+serverInfo.getIpAddress()+":"+serverInfo.getHttpPort()+"/universaltestsoftware_server_api/outer/client/bootLogPage";
String result = HttpRequest.post(url)
.header("Content-Type", "application/json")
.body(JSONUtil.toJsonStr(pageLogDto))
.execute()
.body();
if (StringUtils.isBlank(result)){
throw new RuntimeException("连接失败");
}
return result;
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException("连接失败");
}
}
@ApiOperation("通过服务端id删除日志")
@PostMapping("/deleteLog")
private String deleteLog(@RequestBody BootLogDeleteDto bootLogDeleteDto) {
ServerInfo serverInfo = serverMapper.selectById(bootLogDeleteDto.getServerId());
if (serverInfo==null){
throw new RuntimeException("服务端不存在");
}
try {
String url = "http://"+serverInfo.getIpAddress()+":"+serverInfo.getHttpPort()+"/universaltestsoftware_server_api/outer/client/bootLogDelete";
String result = HttpRequest.post(url)
.header("Content-Type", "application/json")
.body(JSONUtil.toJsonStr(bootLogDeleteDto))
.execute()
.body();
if (StringUtils.isBlank(result)){
throw new RuntimeException("连接失败");
}
return result;
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException("连接失败");
}
}
}

View File

@@ -0,0 +1,62 @@
package com.cbsd.universaltestsoftware_client.controller;
import com.cbsd.universaltestsoftware_client.entity.Parser;
import com.cbsd.universaltestsoftware_client.entity.ParserProtocol;
import com.cbsd.universaltestsoftware_client.nettyclient.entity.ReceiveTcpContent;
import com.cbsd.universaltestsoftware_client.service.ParserService;
import com.cbsd.universaltestsoftware_client.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@RestController
@Api(tags = "解析器管理")
@RequestMapping("/api/parser")
public class ParserController {
@Resource
private ParserService parserService;
@ApiOperation("获取解析器列表")
@GetMapping("/getParserList")
public Result<List<Parser>> getParserList(@RequestParam String channelId) {
return parserService.getParserList(channelId);
}
@ApiOperation("修改或者新增解析器")
@PostMapping("/saveOrUpdateParser")
public Result<String> saveOrUpdateParser(@RequestBody Parser parser) {
return parserService.saveOrUpdateParser(parser);
}
@ApiOperation("删除解析器")
@GetMapping("/deleteParserById")
public Result<String> deleteParserById(@RequestParam String parserId) {
return parserService.deleteParserById(parserId);
}
@ApiOperation("解析器添加或者修改协议")
@PostMapping("/addProtocol")
public Result<String> addProtocol(@RequestBody @Validated List<ParserProtocol> parserProtocol) {
return parserService.addProtocol(parserProtocol);
}
@ApiOperation("解析器协议列表")
@GetMapping("/getProtocolList")
public Result<List<ParserProtocol>> getProtocolList(@RequestParam String parserId) {
return parserService.getProtocolList(parserId);
}
@ApiOperation("删除解析器协议")
@GetMapping("/deleteParserProtocolById")
public Result<String> deleteParserProtocolById(@RequestParam String parserProtocolId) {
return parserService.deleteParserProtocolById(parserProtocolId);
}
}

View File

@@ -0,0 +1,68 @@
package com.cbsd.universaltestsoftware_client.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cbsd.universaltestsoftware_client.dto.ProtocolPageDto;
import com.cbsd.universaltestsoftware_client.entity.Protocol;
import com.cbsd.universaltestsoftware_client.service.ProtocolService;
import com.cbsd.universaltestsoftware_client.util.Result;
import com.cbsd.universaltestsoftware_client.vo.ProtocolSaveVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
/**
* <p>
* 协议 前端控制器
* </p>
*
* @author admin
* @since 2025-09-02
*/
@RestController
@Api(tags = "协议管理")
@RequestMapping("/api/protocol")
public class ProtocolController {
@Resource
private ProtocolService protocolService;
@ApiOperation("获取协议列表")
@PostMapping("/pageListProtocol")
public Result<Page<Protocol>> pageListProtocol(@RequestBody ProtocolPageDto dto) {
return protocolService.pageListProtocol(dto);
}
@ApiOperation("添加或者修改协议")
@PostMapping("/saveOrUpdateProtocol")
public Result<ProtocolSaveVo> saveOrUpdateProtocol(@RequestBody Protocol protocol) {
return protocolService.saveOrUpdateProtocol(protocol);
}
@ApiOperation("删除协议")
@GetMapping("/deleteProtocolById")
public Result<String> deleteProtocolById(@RequestParam String protocolId) {
return protocolService.deleteProtocolById(protocolId);
}
@ApiOperation("协议导入")
@PostMapping("/import")
public Result<String> importProtocol(MultipartFile file) {
if (file == null) {
return Result.error("文件不能为空");
}
if (file.isEmpty()) {
return Result.error("文件无效或文件内容为空");
}
if (StringUtils.isBlank(file.getOriginalFilename())) {
return Result.error("文件名无效");
}
if (!(file.getOriginalFilename().endsWith(".xlsx") || file.getOriginalFilename().endsWith(".xls"))) {
return Result.error("文件格式错误");
}
return protocolService.importProtocol(file);
}
}

View File

@@ -0,0 +1,59 @@
package com.cbsd.universaltestsoftware_client.controller;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cbsd.universaltestsoftware_client.config.BasePage;
import com.cbsd.universaltestsoftware_client.entity.Scheme;
import com.cbsd.universaltestsoftware_client.service.SchemeService;
import com.cbsd.universaltestsoftware_client.util.DateUtils;
import com.cbsd.universaltestsoftware_client.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* <p>
* 方案 前端控制器
* </p>
*
* @author admin
* @since 2025-09-01
*/
@RestController
@Api(tags = "方案")
@RequestMapping("/api/scheme")
public class SchemeController {
@Resource
private SchemeService schemeService;
@PostMapping("/pageList")
@ApiOperation("获取方案列表")
public Result<Page<Scheme>> pageList(@RequestBody BasePage<Scheme> basePage) {
return schemeService.pageList(basePage);
}
@ApiOperation("添加或者修改方案")
@PostMapping("/saveOrUpdate")
public Result<String> saveOrUpdate(@RequestBody @Validated Scheme scheme) {
if (StringUtils.isNotBlank(scheme.getSchemeId())) {
scheme.setUpdateTime(DateUtils.dateToString());
} else {
scheme.setCreateTime(DateUtils.dateToString());
}
return schemeService.saveOrUpdate(scheme) ? Result.success("成功") : Result.error("失败");
}
@GetMapping("/deleteById")
@ApiOperation("删除方案")
public Result<String> deleteById(@RequestParam String schemeId) {
return schemeService.deleteScheme(schemeId);
}
}

View File

@@ -0,0 +1,180 @@
package com.cbsd.universaltestsoftware_client.controller;
import com.cbsd.universaltestsoftware_client.dto.ScriptContentDto;
import com.cbsd.universaltestsoftware_client.dto.ScriptDto;
import com.cbsd.universaltestsoftware_client.dto.ScriptFileContentDto;
import com.cbsd.universaltestsoftware_client.script.ScriptManager;
import com.cbsd.universaltestsoftware_client.service.InstructService;
import com.cbsd.universaltestsoftware_client.util.Result;
import com.cbsd.universaltestsoftware_client.vo.InstructScriptVo;
import com.cbsd.universaltestsoftware_client.vo.ScriptTypeVo;
import com.cbsd.universaltestsoftware_client.vo.ScriptVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
@RestController
@Api(tags = "脚本管理")
@RequestMapping("/api/script")
public class ScriptController {
@Resource
private ScriptManager scriptManager;
@Resource
private InstructService instructService;
@ApiOperation("刷新脚本")
@GetMapping("/recompileAllScript")
public Result<String> recompileAllScript() {
scriptManager.recompileAllScript();
return Result.success();
}
@ApiOperation("获取脚本类型列表")
@GetMapping("/getScriptTypeList")
public Result<List<ScriptTypeVo>> getScriptTypeList() {
return Result.success(scriptManager.getScriptTypeList());
}
@ApiOperation("根据脚本类型获取脚本列表")
@GetMapping("/getScriptList")
public Result<List<ScriptVo>> getScriptList(@RequestParam String scriptType) {
//判断scriptType是否是ScriptManager.ScriptType
if (StringUtils.isBlank(scriptType)) {
return Result.error("脚本类型不能为空");
}
if (!ScriptManager.ScriptType.getValues().contains(scriptType)) {
return Result.error("类型错误");
}
return Result.success(scriptManager.getScriptList(scriptType));
}
@ApiOperation("编译脚本")
@PostMapping("/compileScript")
public Result<String> compileScript(@RequestBody ScriptDto dto) {
if (dto == null) {
return Result.error("参数错误");
}
if (StringUtils.isBlank(dto.getScriptType())) {
return Result.error("脚本类型不能为空");
}
if (!ScriptManager.ScriptType.getValues().contains(dto.getScriptType())) {
return Result.error("类型错误");
}
if (StringUtils.isBlank(dto.getScriptFileName())) {
return Result.error("脚本文件名称不能为空");
}
return scriptManager.compileScript(dto.getScriptType(), dto.getScriptFileName());
}
@ApiOperation("删除脚本")
@PostMapping("/deleteScript")
public Result<String> deleteScript(@RequestBody ScriptDto dto) {
if (dto == null) {
return Result.error("参数错误");
}
if (StringUtils.isBlank(dto.getScriptType())) {
return Result.error("脚本类型不能为空");
}
if (!ScriptManager.ScriptType.getValues().contains(dto.getScriptType())) {
return Result.error("类型错误");
}
if (StringUtils.isBlank(dto.getScriptFileName())) {
return Result.error("脚本文件名称不能为空");
}
scriptManager.deleteScript(dto.getScriptType(), dto.getScriptFileName(), dto.getScriptName());
return Result.success();
}
@ApiOperation("上传脚本")
@PostMapping("/uploadScript")
public Result<InstructScriptVo> uploadScript(@RequestParam String instructId, @RequestParam String scriptType, MultipartFile file) {
InstructScriptVo vo = null;
try {
vo = scriptManager.uploadScript(scriptType, file);
instructService.uploadScript(instructId, vo.getScriptType(), vo.getScriptFile());
vo.setInstructId(instructId);
return Result.success(vo);
} catch (Exception e) {
if (vo != null) {
scriptManager.deleteScriptFile(vo.getScriptType(), vo.getScriptFile());
}
return Result.error(e.getMessage());
}
}
@ApiOperation("保存脚本内容")
@PostMapping("/saveScriptContent")
public Result<InstructScriptVo> saveScriptContent(@RequestBody ScriptContentDto dto) {
InstructScriptVo vo = null;
try {
vo = scriptManager.saveScriptContent(dto.getInstructId(), dto.getScriptType(), dto.getScriptContent());
instructService.uploadScriptContent(dto.getInstructId(), vo.getScriptType(), vo.getScriptName(), dto.getScriptContent());
vo.setInstructId(dto.getInstructId());
return Result.success(vo);
} catch (Exception e) {
if (vo != null) {
scriptManager.deleteScriptFile(vo.getScriptType(), vo.getScriptFile());
}
return Result.error(e.getMessage());
}
}
@ApiOperation("获取脚本文件内容")
@GetMapping("/getScriptFileContent")
public Result<String> getScriptFileContent(@RequestParam String filePath) {
if (StringUtils.isBlank(filePath)) {
return Result.error("文件地址不能为空");
}
if (!new File(filePath).exists()) {
return Result.error("文件不存在");
}
try {
String content = new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8);
return Result.success(content);
} catch (IOException e) {
e.printStackTrace();
}
return Result.error("文件读取失败");
}
@ApiOperation("保存脚本文件内容")
@PostMapping("/saveScriptFileContent")
public Result<String> saveScriptFileContent(@RequestBody ScriptFileContentDto dto) {
if (StringUtils.isBlank(dto.getScriptType())) {
return Result.error("脚本类型不能为空");
}
if (!ScriptManager.ScriptType.getValues().contains(dto.getScriptType())) {
return Result.error("类型错误");
}
if (StringUtils.isBlank(dto.getContent())) {
return Result.error("脚本内容不能为空");
}
try {
if (StringUtils.isBlank(dto.getFilePath())) {
//新增
scriptManager.createScriptFile(dto.getScriptType(), dto.getContent());
} else {
//修改
File file = new File(dto.getFilePath());
Files.write(Paths.get(file.getPath()), dto.getContent().getBytes(StandardCharsets.UTF_8));
scriptManager.compileScriptFile(dto.getScriptType(), file);
}
return Result.success();
}catch (Exception e) {
return Result.error(e.getMessage());
}
}
}

View File

@@ -0,0 +1,47 @@
package com.cbsd.universaltestsoftware_client.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cbsd.universaltestsoftware_client.dto.SensorEquipmentDto;
import com.cbsd.universaltestsoftware_client.dto.SensorEquipmentPageDto;
import com.cbsd.universaltestsoftware_client.entity.SensorEquipment;
import com.cbsd.universaltestsoftware_client.service.SensorEquipmentService;
import com.cbsd.universaltestsoftware_client.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@RestController
@Api(tags = "传感设备")
@RequestMapping("/api/sensorEquipment")
public class SensorEquipmentController {
@Resource
private SensorEquipmentService sensorEquipmentService;
@ApiOperation("分页列表")
@PostMapping("/pageList")
public Result<Page<SensorEquipment>> pageList(@RequestBody SensorEquipmentPageDto dto) {
return sensorEquipmentService.pageList(dto);
}
@ApiOperation("获取所有列表")
@GetMapping("/getAllList")
public Result<List<SensorEquipment>> getAllList(@RequestParam(required = false) String channelId) {
return sensorEquipmentService.getAllList(channelId);
}
@ApiOperation("新增或修改")
@PostMapping("/addOrUpdate")
public Result<String> addOrUpdate(@RequestBody SensorEquipmentDto dto){
return sensorEquipmentService.addOrUpdate(dto);
}
@ApiOperation("删除")
@GetMapping("/delete")
public Result<String> delete(@RequestParam String equipmentId) {
return sensorEquipmentService.delete(equipmentId);
}
}

View File

@@ -0,0 +1,76 @@
package com.cbsd.universaltestsoftware_client.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cbsd.universaltestsoftware_client.dto.PageServerInfoDto;
import com.cbsd.universaltestsoftware_client.entity.ServerInfo;
import com.cbsd.universaltestsoftware_client.service.ServeService;
import com.cbsd.universaltestsoftware_client.util.DateUtils;
import com.cbsd.universaltestsoftware_client.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* <p>
* 服务端 前端控制器
* </p>
*
* @author admin
* @since 2025-08-26
*/
@RestController
@Api(tags = "服务端接口")
@RequestMapping("/api/serverTerminal")
public class ServerTerminalController {
@Resource
private ServeService serveService;
@ApiOperation("获取服务端列表")
@PostMapping("/pageList")
public Result<Page<ServerInfo>> pageList(@RequestBody PageServerInfoDto basePage) {
return serveService.pageList(basePage);
}
@ApiOperation("添加或者修改服务端")
@PostMapping("/saveOrUpdate")
public Result<String> saveOrUpdate(@RequestBody @Validated ServerInfo serverInfo) {
if (serverInfo.getServerId() == null) {
serverInfo.setCreateTime(DateUtils.dateToString());
} else {
serverInfo.setUpdateTime(DateUtils.dateToString());
}
return serveService.saveOrUpdate(serverInfo) ? Result.success("成功") : Result.error("失败");
}
@ApiOperation("删除服务端")
@GetMapping("/deleteById")
public Result<String> deleteById(@RequestParam String serverId) {
return serveService.deleteById(serverId);
}
/**
* 断开并移除指定服务端连接
*/
@ApiOperation("断开指定服务端连接")
@GetMapping("/disconnectServer")
public Result<String> disconnectServer(@RequestParam String serverId) {
serveService.disconnectServer(serverId);
return Result.success("已移除服务端[" + serverId + "]的连接");
}
/**
* 连接指定服务端
*/
@ApiOperation("连接指定服务端")
@GetMapping("/connectServer")
public Result<Void> connectServer(@RequestParam String serverId) {
//查询服务端信息
return serveService.connectOrDisconnect(serverId);
}
}

View File

@@ -0,0 +1,52 @@
package com.cbsd.universaltestsoftware_client.controller;
import com.cbsd.universaltestsoftware_client.dto.DataClearDto;
import com.cbsd.universaltestsoftware_client.service.SystemConfigService;
import com.cbsd.universaltestsoftware_client.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@RestController
@Api(tags = "系统配置")
@RequestMapping("/api/config")
public class SystemConfigController {
@Resource
private SystemConfigService systemConfigService;
@ApiOperation("获取显示列列表")
@GetMapping("/getShowColumnList")
public Result<List<String>> getShowColumnList(){
return systemConfigService.getShowColumnList();
}
@ApiOperation("设置显示列列表")
@PostMapping("/setShowColumnList")
public Result<String> setShowColumnList(@RequestBody List<String> columnList){
return systemConfigService.setShowColumnList(columnList);
}
@ApiOperation("获取数据清理上限")
@GetMapping("/getDataClearLimit")
public Result<String> getDataClearLimit() {
return Result.success(systemConfigService.getSystemConfig(2));
}
@ApiOperation("设置数据清理上限")
@PostMapping("/setDataClearLimit")
public Result<Void> setDataClearLimit(@RequestBody DataClearDto dto) {
if (dto == null || dto.getLimit() == null) {
return Result.error("数据上限不能为空");
}
try {
systemConfigService.setSystemConfig(2, String.valueOf(dto.getLimit()));
} catch (Exception e) {
return Result.error("设置失败");
}
return Result.success();
}
}

View File

@@ -0,0 +1,40 @@
package com.cbsd.universaltestsoftware_client.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
public class BatchChangeInstructParamDto {
/**
* 用例id
*/
@ApiModelProperty(value = "用例id")
private String invocationId;
/**
* 指令id列表
*/
@ApiModelProperty(value = "指令id列表")
private List<String> instructIdList;
/**
* 状态 1.启用 0.禁用
*/
@ApiModelProperty(value = "状态 1.启用 0.禁用")
private Integer status;
/**
* 断点 1.是 0.否
*/
@ApiModelProperty(value = "断点 1.是 0.否")
private Integer isDebug;
/**
* 前置等待时间
*/
@ApiModelProperty(value = "前置等待时间")
private Integer leadTime;
/**
* 后置等待时间
*/
@ApiModelProperty(value = "后置等待时间")
private Integer tailTime;
}

View File

@@ -0,0 +1,16 @@
package com.cbsd.universaltestsoftware_client.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import java.util.List;
@Data
public class BatchCopyBelowDTO {
@NotBlank(message = "invocationId不能为空")
private String invocationId;
@NotEmpty(message = "instructIds不能为空")
private List<@NotBlank String> instructIds;
}

View File

@@ -0,0 +1,17 @@
package com.cbsd.universaltestsoftware_client.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
public class BatchMoveBelowDTO {
@NotBlank(message = "invocationId不能为空")
private String invocationId;
@NotNull(message = "移动的id,和sort的list")
private List<SortDto> instructs;
}

View File

@@ -0,0 +1,17 @@
package com.cbsd.universaltestsoftware_client.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class BoardTemperatureDto {
@ApiModelProperty("服务端id")
private String serverId;
@ApiModelProperty( "板卡id")
private String boardId;
@ApiModelProperty( "板卡索引")
private String boardIndex;
}

View File

@@ -0,0 +1,17 @@
package com.cbsd.universaltestsoftware_client.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class BoardTemperatureServerDto {
@ApiModelProperty("服务端id")
private String serverId;
@ApiModelProperty( "板卡id")
private String boardId;
@ApiModelProperty( "板卡索引")
private Integer boardIndex;
}

View File

@@ -0,0 +1,31 @@
package com.cbsd.universaltestsoftware_client.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import java.util.List;
@Data
public class BootLogDeleteDto {
@ApiModelProperty("服务端id")
private String serverId;
@ApiModelProperty("主键ID自增长")
private Long id;
@ApiModelProperty("批量id")
private List<Long> listId;
@ApiModelProperty("日志级别DEBUG, INFO, WARN, ERROR")
private String level;
@ApiModelProperty(value = "开始时间")
private String startTime;
/**
* 结束时间
*/
@ApiModelProperty(value = "结束时间")
private String endTime;
}

View File

@@ -0,0 +1,29 @@
package com.cbsd.universaltestsoftware_client.dto;
import com.cbsd.universaltestsoftware_client.config.BasePage;
import com.cbsd.universaltestsoftware_client.entity.BootLog;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class BootLogPageDto extends BasePage<BootLog> {
@ApiModelProperty("日志级别DEBUG, INFO, WARN, ERROR")
private String level;
@ApiModelProperty(value = "开始时间")
private String startTime;
/**
* 结束时间
*/
@ApiModelProperty(value = "结束时间")
private String endTime;
@ApiModelProperty("日志类型 1.软件日志 2.系统日志")
private Integer logType;
}

View File

@@ -0,0 +1,18 @@
package com.cbsd.universaltestsoftware_client.dto;
import com.cbsd.universaltestsoftware_client.config.BasePage;
import com.cbsd.universaltestsoftware_client.entity.ChannelData;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
public class ChannelDataDto extends BasePage<ChannelData> {
@ApiModelProperty("通道idList")
private List<String> channelIdList;
}

View File

@@ -0,0 +1,22 @@
package com.cbsd.universaltestsoftware_client.dto;
import com.cbsd.universaltestsoftware_client.config.BasePage;
import com.cbsd.universaltestsoftware_client.entity.ChannelDataHistory;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotEmpty;
@EqualsAndHashCode(callSuper = true)
@Data
public class ChannelDataHistoryDto extends BasePage<ChannelDataHistory> {
@ApiModelProperty("通道id")
private String channelId;
@ApiModelProperty("服务端id")
@NotEmpty(message = "服务端id不能为空")
private String serverId;
}

View File

@@ -0,0 +1,15 @@
package com.cbsd.universaltestsoftware_client.dto;
import lombok.Data;
import java.util.List;
@Data
public class ChannelDataQueryAll {
private List<String> channelIds;
private String startTime;
private String endTime;
}

View File

@@ -0,0 +1,18 @@
package com.cbsd.universaltestsoftware_client.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ChannelDataStatisticsDto {
/**
* 数据看板id
*/
@ApiModelProperty("数据看板id")
private String dataBoardId;
/**
* 通道id
*/
@ApiModelProperty("通道id")
private String channelId;
}

View File

@@ -0,0 +1,16 @@
package com.cbsd.universaltestsoftware_client.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ChannelDto {
@ApiModelProperty("通道id")
private String channelId;
@ApiModelProperty("通道名字")
private String channelName;
}

View File

@@ -0,0 +1,28 @@
package com.cbsd.universaltestsoftware_client.dto;
import com.cbsd.universaltestsoftware_client.config.BasePage;
import com.cbsd.universaltestsoftware_client.entity.Channel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ChannelPageDto extends BasePage<Channel> {
@ApiModelProperty("板卡id")
@NotBlank(message = "板卡id不可以为空")
private String boardId;
@ApiModelProperty("服务id")
@NotBlank(message = "服务id不可以为空")
private String serverId;
}

View File

@@ -0,0 +1,17 @@
package com.cbsd.universaltestsoftware_client.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.util.List;
@Data
public class CreateGroupDTO {
@NotBlank
private String invocationId;
@Size(min = 2, message = "至少选择 2 个节点")
private List<@NotBlank String> instructIds;
}

View File

@@ -0,0 +1,11 @@
package com.cbsd.universaltestsoftware_client.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class DataClearDto {
@ApiModelProperty("数据上限")
private Integer limit;
}

View File

@@ -0,0 +1,18 @@
package com.cbsd.universaltestsoftware_client.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
public class DeleteChannelDto {
private List<String> channelIds;
@ApiModelProperty("开始时间")
private String startTime;
@ApiModelProperty("结束时间")
private String endTime;
}

View File

@@ -0,0 +1,18 @@
package com.cbsd.universaltestsoftware_client.dto;
import com.baomidou.mybatisplus.annotation.TableField;
import com.cbsd.universaltestsoftware_client.config.BasePage;
import com.cbsd.universaltestsoftware_client.entity.Download;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class DownloadDto extends BasePage<Download> {
@ApiModelProperty("1:生成中,2:已完成")
@TableField("state")
private Integer state;
@ApiModelProperty("类型 1解析数据 ,2:原数据")
private Integer type;
}

View File

@@ -0,0 +1,46 @@
package com.cbsd.universaltestsoftware_client.dto;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
public class ExportDataBoardDto {
@ApiModelProperty("开始时间")
@NotEmpty(message = "开始时间不能为空")
private String startTime;
@ApiModelProperty("结束时间")
@NotEmpty(message = "结束时间不能为空")
private String endTime;
@ApiModelProperty("看板id")
@NotEmpty(message = "看板id不能为空")
private String dataBoardId;
@ApiModelProperty("参数")
private List<String> param;
@ApiModelProperty("导出类型1:解析,2原数据")
// @NotNull(message = "导出类型不能为空")
private Integer exportType;
/**
* 解析数据类型 1.原码值 2.解析值 3.两者
*/
@ApiModelProperty("解析数据类型 1.原码值 2.解析值 3.两者")
private Integer parseDataType;
@ApiModelProperty("协议ids")
private List<String> protocolIds;
}

View File

@@ -0,0 +1,21 @@
package com.cbsd.universaltestsoftware_client.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(description= "文件信息")
public class FileInfo {
@ApiModelProperty(value = "文件存储相对路径")
private String relativePath;
@ApiModelProperty(value = "文件原始名称")
private String originalFilename;
@ApiModelProperty(value = "网络文件读取路径")
private String nginxFileReadPath;
@ApiModelProperty(value = "文件尺寸大小,单位kb")
private String fileSize;
@ApiModelProperty(value = "文件新名称")
private String newFileName;
}

View File

@@ -0,0 +1,35 @@
package com.cbsd.universaltestsoftware_client.dto;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
public class InsertDataBoardDto {
@ApiModelProperty("数据看板id")
private String dataBoardId;
@ApiModelProperty("看板类型,0:表格,1:曲线")
@TableField("data_board_type")
private Integer dataBoardType;
@ApiModelProperty("看板名字")
@TableField("data_board_name")
private String dataBoardName;
@ApiModelProperty("0:遥测,1:数据回放")
@NotNull(message = "数据类型不能为空")
private Integer dataType;
@ApiModelProperty("通道lsit")
private List<ChannelDto> channelList;
}

View File

@@ -0,0 +1,13 @@
package com.cbsd.universaltestsoftware_client.dto;
import lombok.Data;
@Data
public class InstructCalcDto {
private String data;
private Integer calcMethod;
private Integer byteCount;
}

View File

@@ -0,0 +1,13 @@
package com.cbsd.universaltestsoftware_client.dto;
import lombok.Data;
import java.util.List;
@Data
public class InstructDeleteDto {
private String invocationId;
private List<String> instructIds;
}

View File

@@ -0,0 +1,14 @@
package com.cbsd.universaltestsoftware_client.dto;
import lombok.Data;
@Data
public class InstructDeleteFileDto {
private String instructId;
/**
* 删除文件类型 1.预处理 2.分支条件 3.检查 4.指令数据 5.协议
*/
private Integer deleteFileType;
}

View File

@@ -0,0 +1,35 @@
package com.cbsd.universaltestsoftware_client.dto;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
public class InstructGroupDto {
@ApiModelProperty("指令id")
private String instructId;
@ApiModelProperty("指令名字")
private String instructName;
@ApiModelProperty("指令类型 1.常规指令 2.指令组")
private Integer instructType;
@ApiModelProperty("用列id")
@NotBlank(message = "用列id不能为空")
private String invocationId;
@ApiModelProperty("父级编码")
private String parentEncoding;
@ApiModelProperty("排序")
// @NotNull(message = "排序不能为空")
private Integer sort;
@ApiModelProperty("需要新增在他下方id")
private String inferiorId;
}

View File

@@ -0,0 +1,164 @@
package com.cbsd.universaltestsoftware_client.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.xml.bind.annotation.*;
@Data
@NoArgsConstructor
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = {
"instructId", "instructType", "encoding", "parentEncoding", "parentName",
"instructName", "serverId", "ipAddress", "tcpPort", "instructText",
"channelId", "channelName", "invocationId", "invocationName","operationType", "extraData",
"boardTypeName", "boardIndex", "protocolId", "protocolName", "protocolContent",
"sort", "status", "leadTime", "tailTime", "hitCount", "lastHitTime",
"instructTag", "preProcessScript", "preProcessScriptName", "preProcessScriptParam",
"preProcessScriptFile", "preProcessScriptComment", "repeatCount",
"branchConditionScript", "branchConditionScriptName", "branchConditionScriptFile",
"branchConditionScriptParam", "branchConditionScriptComment",
"checkScript", "checkScriptName", "checkScriptFile", "checkScriptComment",
"instructDataFile", "jumpTarget", "breakPoint"
})
public class InstructItem {
@XmlElement(name = "InstructId")
private String instructId;
@XmlElement(name = "InstructType")
private Integer instructType;
@XmlElement(name = "Encoding")
private String encoding;
@XmlElement(name = "ParentEncoding")
private String parentEncoding;
@XmlElement(name = "ParentName")
private String parentName;
@XmlElement(name = "InstructName")
private String instructName;
@XmlElement(name = "ServerId")
private String serverId;
@XmlElement(name = "IpAddress")
private String ipAddress;
@XmlElement(name = "TcpPort")
private Integer tcpPort;
@XmlElement(name = "InstructText")
private String instructText;
@XmlElement(name = "ChannelId")
private String channelId;
@XmlElement(name = "ChannelName")
private String channelName;
@XmlElement(name = "InvocationId")
private String invocationId;
@XmlElement(name = "InvocationName")
private String invocationName;
@XmlElement(name = "OperationType")
private Integer operationType;
@XmlElement(name = "ExtraData")
private String extraData;
@XmlElement(name = "BoardTypeName")
private String boardTypeName;
@XmlElement(name = "BoardIndex")
private String boardIndex;
@XmlElement(name = "ProtocolId")
private String protocolId;
@XmlElement(name = "ProtocolName")
private String protocolName;
@XmlElement(name = "ProtocolContent")
private String protocolContent;
@XmlElement(name = "Sort")
private Integer sort;
@XmlElement(name = "Status")
private Integer status;
@XmlElement(name = "LeadTime")
private Integer leadTime;
@XmlElement(name = "TailTime")
private Integer tailTime;
@XmlElement(name = "HitCount")
private Integer hitCount;
@XmlElement(name = "LastHitTime")
private String lastHitTime;
@XmlElement(name = "InstructTag")
private String instructTag;
@XmlElement(name = "PreProcessScript")
private String preProcessScript;
@XmlElement(name = "PreProcessScriptName")
private String preProcessScriptName;
@XmlElement(name = "PreProcessScriptParam")
private String preProcessScriptParam;
@XmlElement(name = "PreProcessScriptFile")
private String preProcessScriptFile;
@XmlElement(name = "PreProcessScriptComment")
private String preProcessScriptComment;
@XmlElement(name = "RepeatCount")
private Integer repeatCount;
@XmlElement(name = "BranchConditionScript")
private String branchConditionScript;
@XmlElement(name = "BranchConditionScriptName")
private String branchConditionScriptName;
@XmlElement(name = "BranchConditionScriptFile")
private String branchConditionScriptFile;
@XmlElement(name = "BranchConditionScriptParam")
private String branchConditionScriptParam;
@XmlElement(name = "BranchConditionScriptComment")
private String branchConditionScriptComment;
@XmlElement(name = "CheckScript")
private String checkScript;
@XmlElement(name = "CheckScriptName")
private String checkScriptName;
@XmlElement(name = "CheckScriptFile")
private String checkScriptFile;
@XmlElement(name = "CheckScriptComment")
private String checkScriptComment;
@XmlElement(name = "InstructDataFile")
private String instructDataFile;
@XmlElement(name = "JumpTarget")
private String jumpTarget;
@XmlElement(name = "BreakPoint")
private Integer breakPoint;
}

View File

@@ -0,0 +1,17 @@
package com.cbsd.universaltestsoftware_client.dto;
import com.cbsd.universaltestsoftware_client.config.BasePage;
import com.cbsd.universaltestsoftware_client.entity.Instruct;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class InstructPageDto extends BasePage<Instruct> {
@ApiModelProperty("用列id")
@NotBlank(message = "用列id不能为空")
private String invocationId;
}

View File

@@ -0,0 +1,21 @@
package com.cbsd.universaltestsoftware_client.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.xml.bind.annotation.*;
import java.util.List;
@Data
@NoArgsConstructor
@XmlRootElement(name = "Instructs")
@XmlAccessorType(XmlAccessType.FIELD)
public class InstructXmlDTO {
@XmlElement(name = "Instruct")
private List<InstructItem> instructs;
public InstructXmlDTO(List<InstructItem> instructs) {
this.instructs = instructs;
}
}

View File

@@ -0,0 +1,17 @@
package com.cbsd.universaltestsoftware_client.dto;
import com.cbsd.universaltestsoftware_client.config.BasePage;
import com.cbsd.universaltestsoftware_client.entity.Invocation;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class InvocationPageDto extends BasePage<Invocation> {
@ApiModelProperty("方案id")
@NotBlank(message = "方案id不能为空")
private String schemeId;
}

View File

@@ -0,0 +1,11 @@
package com.cbsd.universaltestsoftware_client.dto;
import lombok.Data;
@Data
public class InvocationSortDto {
private String schemeId;
private String invocationId;
private Integer sort;
}

View File

@@ -0,0 +1,19 @@
package com.cbsd.universaltestsoftware_client.dto;
import com.cbsd.universaltestsoftware_client.config.BasePage;
import com.cbsd.universaltestsoftware_client.entity.Board;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageBoard extends BasePage<Board> {
@ApiModelProperty("服务端id")
@NotEmpty(message = "服务端id不能为空")
private String serverId;
}

View File

@@ -0,0 +1,30 @@
package com.cbsd.universaltestsoftware_client.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Data
public class PageChannelDataDto {
@ApiModelProperty("开始时间")
private String startTime;
@ApiModelProperty("结束时间")
private String endTime;
@ApiModelProperty("条数")
@NotNull(message = "条数不能为空")
private Integer pageSize;
@ApiModelProperty("数据看板id")
@NotEmpty(message = "数据看板id不能为空")
private String dataBoardId;
private Integer want;
private String lastTime;
}

View File

@@ -0,0 +1,13 @@
package com.cbsd.universaltestsoftware_client.dto;
import com.cbsd.universaltestsoftware_client.config.BasePage;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
@Data
public class PageLogDto extends BasePage {
@ApiModelProperty("服务端id")
@NotEmpty(message = "服务端id不能为空")
private String serverId;
}

View File

@@ -0,0 +1,14 @@
package com.cbsd.universaltestsoftware_client.dto;
import com.cbsd.universaltestsoftware_client.config.BasePage;
import com.cbsd.universaltestsoftware_client.entity.ServerInfo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class PageServerInfoDto extends BasePage<ServerInfo> {
@ApiModelProperty("连接状态0不连接,1要连接")
private Integer connectStatus;
}

View File

@@ -0,0 +1,295 @@
package com.cbsd.universaltestsoftware_client.dto;
import com.alibaba.excel.annotation.ExcelProperty;
public class ProtocolImport {
public static class BasicInfo {
@ExcelProperty("readName")
private String readName= "";
@ExcelProperty("frameHeadValue")
private String frameHeadValue= "";
@ExcelProperty("frameTailValue")
private String frameTailValue= "";
@ExcelProperty("checkStartSn")
private String checkStartSn= "";
@ExcelProperty("checkEndSn")
private String checkEndSn= "";
@ExcelProperty("verifyScript")
private String verifyScript= "";
public String getReadName() {
return readName;
}
public void setReadName(String readName) {
this.readName = readName;
}
public String getFrameHeadValue() {
return frameHeadValue;
}
public void setFrameHeadValue(String frameHeadValue) {
this.frameHeadValue = frameHeadValue;
}
public String getFrameTailValue() {
return frameTailValue;
}
public void setFrameTailValue(String frameTailValue) {
this.frameTailValue = frameTailValue;
}
public String getCheckStartSn() {
return checkStartSn;
}
public void setCheckStartSn(String checkStartSn) {
this.checkStartSn = checkStartSn;
}
public String getCheckEndSn() {
return checkEndSn;
}
public void setCheckEndSn(String checkEndSn) {
this.checkEndSn = checkEndSn;
}
public String getVerifyScript() {
return verifyScript;
}
public void setVerifyScript(String verifyScript) {
this.verifyScript = verifyScript;
}
}
public static class Filed {
@ExcelProperty("sn")
private String sn = "";
@ExcelProperty("label")
private String label = "";
@ExcelProperty("readName")
private String readName = "";
@ExcelProperty("phyType")
private String phyType = "";
@ExcelProperty("timeFormat")
private String timeFormat = "";
@ExcelProperty("bitslen")
private String bitslen = "";
@ExcelProperty("bitmask")
private String bitmask = "";
@ExcelProperty("phyInnerScript")
private String phyInnerScript = "";
@ExcelProperty("phyScript")
private String phyScript = "";
@ExcelProperty("endian")
private String endian = "";
@ExcelProperty("type")
private String type = "";
@ExcelProperty("frame")
private String frame = "";
@ExcelProperty("calcScript")
private String calcScript = "";
@ExcelProperty("phyUnit")
private String phyUnit = "";
@ExcelProperty("binStr")
private String binStr = "";
@ExcelProperty("hex")
private String hex = "";
@ExcelProperty("phy")
private String phy = "";
@ExcelProperty("avg")
private String avg = "";
@ExcelProperty("min")
private String min = "";
@ExcelProperty("max")
private String max = "";
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getReadName() {
return readName;
}
public void setReadName(String readName) {
this.readName = readName;
}
public String getPhyType() {
return phyType;
}
public void setPhyType(String phyType) {
this.phyType = phyType;
}
public String getTimeFormat() {
return timeFormat;
}
public void setTimeFormat(String timeFormat) {
this.timeFormat = timeFormat;
}
public String getBitslen() {
return bitslen;
}
public void setBitslen(String bitslen) {
this.bitslen = bitslen;
}
public String getBitmask() {
return bitmask;
}
public void setBitmask(String bitmask) {
this.bitmask = bitmask;
}
public String getPhyInnerScript() {
return phyInnerScript;
}
public void setPhyInnerScript(String phyInnerScript) {
this.phyInnerScript = phyInnerScript;
}
public String getPhyScript() {
return phyScript;
}
public void setPhyScript(String phyScript) {
this.phyScript = phyScript;
}
public String getEndian() {
return endian;
}
public void setEndian(String endian) {
this.endian = endian;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getFrame() {
return frame;
}
public void setFrame(String frame) {
this.frame = frame;
}
public String getCalcScript() {
return calcScript;
}
public void setCalcScript(String calcScript) {
this.calcScript = calcScript;
}
public String getPhyUnit() {
return phyUnit;
}
public void setPhyUnit(String phyUnit) {
this.phyUnit = phyUnit;
}
public String getBinStr() {
return binStr;
}
public void setBinStr(String binStr) {
this.binStr = binStr;
}
public String getHex() {
return hex;
}
public void setHex(String hex) {
this.hex = hex;
}
public String getPhy() {
return phy;
}
public void setPhy(String phy) {
this.phy = phy;
}
public String getAvg() {
return avg;
}
public void setAvg(String avg) {
this.avg = avg;
}
public String getMin() {
return min;
}
public void setMin(String min) {
this.min = min;
}
public String getMax() {
return max;
}
public void setMax(String max) {
this.max = max;
}
}
public static class VariableLength {
@ExcelProperty("value")
private String value= "";
@ExcelProperty("length")
private String length= "";
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getLength() {
return length;
}
public void setLength(String length) {
this.length = length;
}
}
}

View File

@@ -0,0 +1,15 @@
package com.cbsd.universaltestsoftware_client.dto;
import com.baomidou.mybatisplus.annotation.TableField;
import com.cbsd.universaltestsoftware_client.entity.DataBoardChannel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
public class ProtocolNameListDto extends DataBoardChannel {
@ApiModelProperty("协议参数list")
@TableField(exist = false)
private List<DataBoardChannel> parameterList;
}

View File

@@ -0,0 +1,16 @@
package com.cbsd.universaltestsoftware_client.dto;
import com.cbsd.universaltestsoftware_client.config.BasePage;
import com.cbsd.universaltestsoftware_client.entity.Protocol;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class ProtocolPageDto extends BasePage<Protocol> {
@ApiModelProperty("协议类型 1.解析 2.指令")
private Integer protocolType;
}

View File

@@ -0,0 +1,14 @@
package com.cbsd.universaltestsoftware_client.dto;
import lombok.Data;
@Data
public class ScriptContentDto {
private String instructId;
private String scriptType;
private String scriptContent;
}

View File

@@ -0,0 +1,13 @@
package com.cbsd.universaltestsoftware_client.dto;
import lombok.Data;
@Data
public class ScriptDto {
private String scriptType;
private String scriptFileName;
private String scriptName;
}

View File

@@ -0,0 +1,13 @@
package com.cbsd.universaltestsoftware_client.dto;
import lombok.Data;
@Data
public class ScriptFileContentDto {
private String scriptType;
private String filePath;
private String content;
}

View File

@@ -0,0 +1,32 @@
package com.cbsd.universaltestsoftware_client.dto;
import lombok.Data;
@Data
public class SensorEquipmentDto {
/**
* 设备id
*/
private String equipmentId;
/**
* 设备名称
*/
private String equipmentName;
/**
* 设备描述
*/
private String equipmentDesc;
/**
* 设备参数
*/
private String equipmentParam;
/**
* 通道id
*/
private String channelId;
/**
* 通道id
*/
private String channelAddress;
}

View File

@@ -0,0 +1,15 @@
package com.cbsd.universaltestsoftware_client.dto;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cbsd.universaltestsoftware_client.entity.SensorEquipment;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class SensorEquipmentPageDto extends Page<SensorEquipment> {
private String equipmentName;
private String channelId;
}

View File

@@ -0,0 +1,27 @@
package com.cbsd.universaltestsoftware_client.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
public class ServerPageChannelDataDto {
@ApiModelProperty("开始时间")
private Long startTime;
@ApiModelProperty("结束时间")
private Long endTime;
@ApiModelProperty("条数")
@NotNull(message = "条数不能为空")
private Integer pageSize;
@ApiModelProperty("数据看板id")
@NotEmpty(message = "数据看板id不能为空")
private String dataBoardId;
private List<String> channelIds;
}

View File

@@ -0,0 +1,16 @@
package com.cbsd.universaltestsoftware_client.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
public class SortDto {
@NotBlank(message = "instructId不能为空")
private String instructId;
@NotNull(message = "sort不能为空")
private Integer sort;
}

View File

@@ -0,0 +1,25 @@
package com.cbsd.universaltestsoftware_client.dto;
public class SubmitAndCompile {
private String className;
private String code;
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}

View File

@@ -0,0 +1,68 @@
package com.cbsd.universaltestsoftware_client.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
/**
* <p>
* 板卡
* </p>
*
* @author admin
* @since 2025-08-26
*/
@Getter
@Setter
/*@TableName("board")*/
@ApiModel(value = "Board对象", description = "板卡")
public class Board {
@ApiModelProperty("板卡id")
private String boardId;
@ApiModelProperty("板卡类型主键Id")
@NotBlank(message = "板卡类型不能为空")
private String boardTypeId;
@NotBlank(message = "服务id不能为空")
private String serverId;
@ApiModelProperty("板卡名字")
@NotBlank(message = "板卡名字不能为空")
private String boardName;
@ApiModelProperty("板卡编号")
@NotBlank(message = "板卡编号不能为空")
private String boardIndex;
@ApiModelProperty("状态,0不在线1在线")
private Integer onlineState;
@ApiModelProperty("通道数量")
private Integer channelNum;
@ApiModelProperty("创建时间")
private String createTime;
@ApiModelProperty("修改时间")
private String updateTime;
@ApiModelProperty("是否删除0否1是")
private String isDelete;
@ApiModelProperty("板卡类型名称 用户看")
@TableField(exist = false)
private String boardTypeName;
}

View File

@@ -0,0 +1,65 @@
package com.cbsd.universaltestsoftware_client.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 系统启动日志表,记录应用程序运行过程中的日志信息
* </p>
*
* @author wt
* @since 2025-09-03
*/
@Getter
@Setter
@TableName("boot_log")
@ApiModel(value = "BootLog对象", description = "系统启动日志表,记录应用程序运行过程中的日志信息")
public class BootLog implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("主键ID自增长")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty("事件ID用于唯一标识一个日志事件")
private String eventId;
@ApiModelProperty("事件发生时间")
@JsonFormat(shape = JsonFormat.Shape.STRING,pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime eventDate;
@ApiModelProperty("产生日志的线程名称")
private String thread;
@ApiModelProperty("产生日志的类名")
private String logClass;
@ApiModelProperty("产生日志的方法/函数名")
private String method;
@ApiModelProperty("日志消息内容")
private String message;
@ApiModelProperty("异常堆栈信息")
private String exception;
@ApiModelProperty("日志级别DEBUG, INFO, WARN, ERROR")
private String level;
@ApiModelProperty("日志记录时间")
@JsonFormat(shape = JsonFormat.Shape.STRING,pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime time;
}

View File

@@ -0,0 +1,65 @@
package com.cbsd.universaltestsoftware_client.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class Channel {
@ApiModelProperty("通道id")
@TableId(value = "channel_id", type = IdType.ASSIGN_UUID)
private String channelId;
@ApiModelProperty("通道类型id")
private String channelTypeId;
@ApiModelProperty("服务id")
@NotBlank(message = "服务id不能为空")
private String serverId;
@ApiModelProperty("通道路径")
private String channelPath;
@ApiModelProperty("板卡id")
private String boardId;
@ApiModelProperty("解析数量")
private int parsingQuantity;
@ApiModelProperty("字节流量")
private int byteCount;
@ApiModelProperty("通道名称")
private String channelName;
@ApiModelProperty("创建时间")
@TableField(fill = FieldFill.INSERT)
private String createTime;
@ApiModelProperty("更新时间")
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateTime;
@ApiModelProperty("是否删除0否1是")
private String isDelete;
@ApiModelProperty("读写通道类型")
private String rwChannelType;
@ApiModelProperty("是否允许修改通道类型 ")
private Integer isUpType;
@ApiModelProperty("通道类型 程序使用")
@TableField(exist = false)
private String channelType;
@ApiModelProperty("通道类型 用户看")
@TableField(exist = false)
private String channelTypeName;
}

View File

@@ -0,0 +1,46 @@
package com.cbsd.universaltestsoftware_client.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 解析的数据
* @TableName channel_data
*/
@TableName(value ="channel_data")
@Data
public class ChannelData {
/**
* 解析数据id
*/
@TableId
private String dataId;
/**
* 通道id
*/
private String channelId;
/**
* 数据内容
*/
private String data;
/**
* 协议id
*/
private String protocolId;
/**
* 协议内容
*/
private String protocolContent;
/**
* 数据时间
*/
private String time;
}

View File

@@ -0,0 +1,61 @@
package com.cbsd.universaltestsoftware_client.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
/**
* <p>
* 通道历史数据
* </p>
*
* @author wt
* @since 2025-09-28
*/
@Getter
@Setter
@TableName("channel_data_history")
@ApiModel(value = "ChannelDataHistory对象", description = "通道历史数据")
public class ChannelDataHistory implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("通道历史数据id")
@TableId(value = "channel_data_history_id", type = IdType.ASSIGN_UUID)
private String channelDataHistoryId;
@ApiModelProperty("通道id")
private String channelId;
@ApiModelProperty("创建时间")
private String createTime;
@ApiModelProperty("是否删除0否1是")
private String isDelete;
@ApiModelProperty("数据信息")
private byte[] content;
@ApiModelProperty("数据字符串")
@TableField(exist = false)
private String contentString;
@ApiModelProperty("时间戳")
private Long timestamp;
/**
* 额外数据
*/
@ApiModelProperty("额外数据")
private String extraData;
}

View File

@@ -0,0 +1,41 @@
package com.cbsd.universaltestsoftware_client.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 通道协议命中次数
* @TableName channel_data_hit
*/
@TableName(value ="channel_data_hit")
@Data
public class ChannelDataHit {
/**
* 命中id
*/
@TableId
private String hitId;
/**
* 通道id
*/
private String channelId;
/**
* 协议id
*/
private String protocolId;
/**
* 命中次数
*/
private Integer hitCount;
/**
* 命中更新时间
*/
private String updateTime;
}

View File

@@ -0,0 +1,36 @@
package com.cbsd.universaltestsoftware_client.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 通道流量统计
* @TableName channel_data_traffic
*/
@TableName(value ="channel_data_traffic")
@Data
public class ChannelDataTraffic {
/**
* 数据流量id
*/
@TableId
private String dataTrafficId;
/**
* 通道id
*/
private String channelId;
/**
* 字节数
*/
private Integer byteCount;
/**
* 更新时间
*/
private String updateTime;
}

View File

@@ -0,0 +1,50 @@
package com.cbsd.universaltestsoftware_client.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* <p>
* 数据看板
* </p>
*
* @author admin
* @since 2025-09-10
*/
@Getter
@Setter
@TableName("data_board")
@ApiModel(value = "DataBoard对象", description = "数据看板")
public class DataBoard {
@ApiModelProperty("数据看板id")
@TableId(value = "data_board_id", type = IdType.ASSIGN_UUID)
private String dataBoardId;
@ApiModelProperty("看板类型,0:表格,1:曲线")
@TableField("data_board_type")
private Integer dataBoardType;
@ApiModelProperty("看板名字")
@TableField("data_board_name")
private String dataBoardName;
@ApiModelProperty("创建时间")
@TableField("create_time")
private String createTime;
@ApiModelProperty("0:遥测,1:数据回放")
private Integer dataType;
@ApiModelProperty("通道list")
@TableField(exist = false)
private List<DataBoardChannel> dataBoardChannelList;
}

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