第一次提交

This commit is contained in:
zg 2025-04-09 10:19:30 +08:00
commit 6f63679c56
247 changed files with 18383 additions and 0 deletions

31
.gitignore vendored Normal file
View File

@ -0,0 +1,31 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**
### 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/
### VS Code ###
.vscode/

310
mvnw vendored Normal file
View File

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

182
mvnw.cmd vendored Normal file
View File

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

294
pom.xml Normal file
View File

@ -0,0 +1,294 @@
<?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>
<groupId>com.eleadmin</groupId>
<artifactId>artwork</artifactId>
<version>1.5.0</version>
<name>ele-admin-api</name>
<description>EleAdminApi project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>17</java.version>
<poi.version>5.2.4</poi.version>
<ooxml-schemas.version>1.4</ooxml-schemas.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<!-- spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- spring-boot-test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- spring-boot-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- spring-boot-aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- spring-boot-configuration-processor -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.6</version>
</dependency>
<!-- mybatis-plus-generator -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.6</version>
</dependency>
<!-- hutool -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.15</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>${ooxml-schemas.version}</version>
</dependency>
<!-- easy poi -->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.4.0</version>
<exclusions>
<exclusion>
<artifactId>poi</artifactId>
<groupId>org.apache.poi</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- tika, 用于FileServer获取content-type -->
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version> <!-- 2022年最新稳定版 -->
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.2</version>
<exclusions>
<exclusion>
<artifactId>poi</artifactId>
<groupId>org.apache.poi</groupId>
</exclusion>
<exclusion>
<artifactId>poi-ooxml</artifactId>
<groupId>org.apache.poi</groupId>
</exclusion>
<exclusion>
<artifactId>poi-ooxml-schemas</artifactId>
<groupId>org.apache.poi</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-io</artifactId>
<groupId>commons-io</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- open office, 用于文档转pdf实现在线预览 -->
<dependency>
<groupId>com.github.livesense</groupId>
<artifactId>jodconverter-core</artifactId>
<version>1.0.5</version>
<exclusions>
<exclusion>
<artifactId>commons-io</artifactId>
<groupId>commons-io</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- spring-boot-mail -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!-- 模板引擎, 用于邮件、代码生成等 -->
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>beetl</artifactId>
<version>3.6.1.RELEASE</version>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<!-- spring security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- jjwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
</dependency>
<!--代码生成需要的模板的引起-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- mybatis-plus-generator -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.6</version>
</dependency>
<!-- 图形验证码 -->
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
<version>1.6.2</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>aliYunMaven</id>
<url>https://maven.aliyun.com/repository/public</url>
</repository>
</repositories>
</project>

View File

@ -0,0 +1,110 @@
package com.eleadmin;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.io.File;
import java.sql.Types;
import java.util.Arrays;
import java.util.Collections;
public class CodeGenerator {
public static class DataSourceProperties {
public static final String jdbcUrl = "jdbc:mysql://actrst.cn:12206/artwork?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8";
public static final String username = "root";
public static final String password = "I2L4DP2C519:Wov";
}
public static class Config {
//项目根目录
public static String rootPath=System.getProperty("user.dir");
public static String author="zg";
//xml文件路径
public static StringBuilder xmlPath=new StringBuilder();
//java文件生成根路径
public static StringBuilder outputDir=new StringBuilder();
//自定义一个公共PO用于存放公共字段并且标记为序列化
public static String superEntity="";
//公用的字段
public static final String[] commonFields = {""};
//开发人员可以在这里修改各自项目的配置
//todo 如果是多模块需要填写模块名如果不需要可以为空串
public static String module="";
//todo 代码根包名
public static String parent_package="com.eleadmin.common.flowStep";
//todo 需要生成的表
public static String[] tables=new String[]{"f_step","f_field","f_step_table","f_step_table_field"};
//todo 表的前缀,如果不需要填空
public static String[] prefix=new String[]{"f"};
static{
outputDir.append(rootPath).append(File.separator).append(module).append("/src/main/java");
xmlPath.append(rootPath).append(File.separator).append(module).append("/src/main/java/com/eleadmin/common/flowStep/mapper/xml/");
}
}
public static void main(String[] args) {
FastAutoGenerator.create(DataSourceProperties.jdbcUrl, DataSourceProperties.username, DataSourceProperties.password)
//全局配置
.globalConfig(builder -> {
builder.author(Config.author)
.outputDir(Config.outputDir.toString());
})
//类型映射配置
.dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
int typeCode = metaInfo.getJdbcType().TYPE_CODE;
//自定义类型转换配置
if (typeCode == Types.SMALLINT || typeCode == Types.TINYINT) {
return DbColumnType.INTEGER;
}
return typeRegistry.getColumnType(metaInfo);
}))
//包配置
.packageConfig(builder -> {
builder.parent(Config.parent_package)
.pathInfo(Collections.singletonMap(OutputFile.xml, Config.xmlPath.toString()));
})
//自定义配置
.injectionConfig(builder -> {
builder.customFile(consumer-> consumer
.fileName("Mapper.xml")
.filePath(Config.xmlPath.toString())
.enableFileOverride()
.templatePath("/templates/mapper.xml.ftl"))
;
})
//具体的生成文件的策略配置
.strategyConfig(builder -> {
builder.addInclude(Arrays.asList(Config.tables))
// .enableSkipView()
.addTablePrefix(Arrays.asList(Config.prefix))
.entityBuilder()
.superClass(Config.superEntity)
.addIgnoreColumns(Config.commonFields)
.enableFileOverride()
.enableLombok()
//controller配置启用rest风格才会使用@RestController注解
.controllerBuilder()
.enableRestStyle()
//开启生成mapper
.mapperBuilder()
.enableBaseResultMap()
.enableBaseColumnList()
//由于此版本Mapper.java与xml文件是一起生成的所以适配我们的规范此处不开启mapper覆盖由自定义配置进行生成我们的xml文件
// .enableFileOverride()
;
})
//模板配置如果你没有自定义的一些模板配置这里直接使用默认即可
//模板引擎配置
.templateEngine(new FreemarkerTemplateEngine())
.execute();
}
}

View File

@ -0,0 +1,30 @@
package com.eleadmin;
import com.eleadmin.common.core.config.ConfigProperties;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.annotation.MapperScans;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* 启动类
* Created by EleAdmin on 2018-02-22 11:29:03
*/
@EnableAsync
@EnableTransactionManagement
@MapperScans({
@MapperScan("com.eleadmin.**.mapper"),
@MapperScan("com.eleadmin.**.dao")
})
@EnableConfigurationProperties(ConfigProperties.class)
@SpringBootApplication
public class EleAdminApplication {
public static void main(String[] args) {
SpringApplication.run(EleAdminApplication.class, args);
}
}

View File

@ -0,0 +1,93 @@
package com.eleadmin.common.core;
/**
* 系统常量
* Created by EleAdmin on 2019-10-29 15:55
*/
public class Constants {
/**
* 默认成功码
*/
public static final int RESULT_OK_CODE = 0;
/**
* 默认失败码
*/
public static final int RESULT_ERROR_CODE = 1;
/**
* 默认成功信息
*/
public static final String RESULT_OK_MSG = "操作成功";
/**
* 默认失败信息
*/
public static final String RESULT_ERROR_MSG = "操作失败";
/**
* 无权限错误码
*/
public static final int UNAUTHORIZED_CODE = 403;
/**
* 无权限提示信息
*/
public static final String UNAUTHORIZED_MSG = "没有访问权限";
/**
* 未认证错误码
*/
public static final int UNAUTHENTICATED_CODE = 401;
/**
* 未认证提示信息
*/
public static final String UNAUTHENTICATED_MSG = "请先登录";
/**
* 登录过期错误码
*/
public static final int TOKEN_EXPIRED_CODE = 401;
/**
* 登录过期提示信息
*/
public static final String TOKEN_EXPIRED_MSG = "登录已过期";
/**
* 非法token错误码
*/
public static final int BAD_CREDENTIALS_CODE = 401;
/**
* 非法token提示信息
*/
public static final String BAD_CREDENTIALS_MSG = "请退出重新登录";
/**
* 表示升序的值
*/
public static final String ORDER_ASC_VALUE = "asc";
/**
* 表示降序的值
*/
public static final String ORDER_DESC_VALUE = "desc";
/**
* token通过header传递的名称
*/
public static final String TOKEN_HEADER_NAME = "Authorization";
/**
* token通过参数传递的名称
*/
public static final String TOKEN_PARAM_NAME = "access_token";
/**
* token认证类型
*/
public static final String TOKEN_TYPE = "Bearer";
}

View File

@ -0,0 +1,41 @@
package com.eleadmin.common.core.annotation;
import java.lang.annotation.*;
/**
* 操作日志记录注解
*
* @author EleAdmin
* @since 2020-03-21 17:03:08
*/
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OperationLog {
/**
* 操作功能
*/
String value() default "";
/**
* 操作模块
*/
String module() default "";
/**
* 备注
*/
String comments() default "";
/**
* 是否记录请求参数
*/
boolean param() default true;
/**
* 是否记录返回结果
*/
boolean result() default true;
}

View File

@ -0,0 +1,21 @@
package com.eleadmin.common.core.annotation;
import java.lang.annotation.*;
/**
* 操作日志模块注解
*
* @author EleAdmin
* @since 2021-09-01 20:48:16
*/
@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface OperationModule {
/**
* 模块名称
*/
String value();
}

View File

@ -0,0 +1,22 @@
package com.eleadmin.common.core.annotation;
import java.lang.annotation.*;
/**
* 查询条件注解
*
* @author EleAdmin
* @since 2021-09-01 20:48:16
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface QueryField {
// 字段名称
String value() default "";
// 查询方式
QueryType type() default QueryType.LIKE;
}

View File

@ -0,0 +1,42 @@
package com.eleadmin.common.core.annotation;
/**
* 查询方式
*
* @author EleAdmin
* @since 2021-09-01 20:48:16
*/
public enum QueryType {
// 等于
EQ,
// 不等于
NE,
// 大于
GT,
// 大于等于
GE,
// 小于
LT,
// 小于等于
LE,
// 包含
LIKE,
// 不包含
NOT_LIKE,
// 结尾等于
LIKE_LEFT,
// 开头等于
LIKE_RIGHT,
// 为NULL
IS_NULL,
// 不为空
IS_NOT_NULL,
// IN
IN,
// NOT IN
NOT_IN,
// IN条件解析逗号分割
IN_STR,
// NOT IN条件解析逗号分割
NOT_IN_STR
}

View File

@ -0,0 +1,213 @@
package com.eleadmin.common.core.aspect;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import cn.hutool.json.JSONObject;
import com.alibaba.druid.support.json.JSONUtils;
import com.eleadmin.common.core.annotation.OperationLog;
import com.eleadmin.common.core.annotation.OperationModule;
import com.eleadmin.common.core.utils.JSONUtil;
import com.eleadmin.common.system.entity.OperationRecord;
import com.eleadmin.common.system.entity.User;
import com.eleadmin.common.system.service.OperationRecordService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Map;
/**
* 操作日志记录
*
* @author EleAdmin
* @since 2020-03-21 16:58:16:05
*/
@Aspect
@Component
public class OperationLogAspect {
@Resource
private OperationRecordService operationRecordService;
// 参数返回结果错误信息等最大保存长度
private static final int MAX_LENGTH = 1000;
// 用于记录请求耗时
private final ThreadLocal<Long> startTime = new ThreadLocal<>();
@Pointcut("@annotation(com.eleadmin.common.core.annotation.OperationLog)")
public void operationLog() {
}
@Before("operationLog()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
startTime.set(System.currentTimeMillis());
}
@AfterReturning(pointcut = "operationLog()", returning = "result")
public void doAfterReturning(JoinPoint joinPoint, Object result) {
saveLog(joinPoint, result, null);
}
@AfterThrowing(value = "operationLog()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
saveLog(joinPoint, null, e);
}
/**
* 保存操作记录
*/
private void saveLog(JoinPoint joinPoint, Object result, Exception e) {
OperationRecord record = new OperationRecord();
// 记录操作耗时
if (startTime.get() != null) {
record.setSpendTime(System.currentTimeMillis() - startTime.get());
}
// 记录当前登录用户id租户id
User user = getLoginUser();
if (user != null) {
record.setUserId(user.getUserId());
record.setTenantId(user.getTenantId());
}
// 记录请求地址请求方式ip
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = (attributes == null ? null : attributes.getRequest());
if (request != null) {
record.setUrl(request.getRequestURI());
record.setRequestMethod(request.getMethod());
UserAgent ua = UserAgentUtil.parse(ServletUtil.getHeaderIgnoreCase(request, "User-Agent"));
record.setOs(ua.getPlatform().toString());
record.setDevice(ua.getOs().toString());
record.setBrowser(ua.getBrowser().toString());
record.setIp(ServletUtil.getClientIP(request));
}
// 记录异常信息
if (e != null) {
record.setStatus(1);
record.setError(StrUtil.sub(e.toString(), 0, MAX_LENGTH));
}
// 记录模块名操作功能请求方法请求参数返回结果
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
record.setMethod(joinPoint.getTarget().getClass().getName() + "." + signature.getName());
Method method = signature.getMethod();
if (method != null) {
OperationLog ol = method.getAnnotation(OperationLog.class);
if (ol != null) {
// 记录操作功能
record.setDescription(getDescription(method, ol));
// 记录操作模块
record.setModule(getModule(joinPoint, ol));
// 记录备注
if (StrUtil.isNotEmpty(ol.comments())) {
record.setComments(ol.comments());
}
// 记录请求参数
if (ol.param() && request != null) {
record.setParams(StrUtil.sub(getParams(joinPoint, request), 0, MAX_LENGTH));
}
// 记录请求结果
if (ol.result() && result != null) {
JSONObject jsonObject = cn.hutool.json.JSONUtil.parseObj(result);
record.setResult(jsonObject.toString());
}
}
}
operationRecordService.saveAsync(record);
}
/**
* 获取当前登录用户
*/
private User getLoginUser() {
Authentication subject = SecurityContextHolder.getContext().getAuthentication();
if (subject != null) {
Object object = subject.getPrincipal();
if (object instanceof User) {
return (User) object;
}
}
return null;
}
/**
* 获取请求参数
*
* @param joinPoint JoinPoint
* @param request HttpServletRequest
* @return String
*/
private String getParams(JoinPoint joinPoint, HttpServletRequest request) {
String params;
Map<String, String> paramsMap = ServletUtil.getParamMap(request);
if (paramsMap.keySet().size() > 0) {
params = JSONUtil.toJSONString(paramsMap);
} else {
StringBuilder sb = new StringBuilder();
for (Object arg : joinPoint.getArgs()) {
if (ObjectUtil.isNull(arg)
|| arg instanceof MultipartFile
|| arg instanceof HttpServletRequest
|| arg instanceof HttpServletResponse) {
continue;
}
sb.append(JSONUtil.toJSONString(arg)).append(" ");
}
params = sb.toString();
}
return params;
}
/**
* 获取操作模块
*
* @param joinPoint JoinPoint
* @param ol OperationLog
* @return String
*/
private String getModule(JoinPoint joinPoint, OperationLog ol) {
if (StrUtil.isNotEmpty(ol.module())) {
return ol.module();
}
OperationModule om = joinPoint.getTarget().getClass().getAnnotation(OperationModule.class);
if (om != null && StrUtil.isNotEmpty(om.value())) {
return om.value();
}
Api api = joinPoint.getTarget().getClass().getAnnotation(Api.class);
if (api != null && api.tags() != null) {
return ArrayUtil.join(api.tags(), ",");
}
return null;
}
/**
* 获取操作功能
*
* @param method Method
* @param ol OperationLog
* @return String
*/
private String getDescription(Method method, OperationLog ol) {
if (StrUtil.isNotEmpty(ol.value())) {
return ol.value();
}
ApiOperation ao = method.getAnnotation(ApiOperation.class);
if (ao != null && StrUtil.isNotEmpty(ao.value())) {
return ao.value();
}
return null;
}
}

View File

@ -0,0 +1,75 @@
package com.eleadmin.common.core.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 系统配置属性
*
* @author EleAdmin
* @since 2021-08-30 17:58:16
*/
@Data
@ConfigurationProperties(prefix = "config")
public class ConfigProperties {
/**
* 文件上传磁盘位置
*/
private Integer uploadLocation = 0;
/**
* 文件上传是否使用uuid命名
*/
private Boolean uploadUuidName = true;
/**
* 文件上传生成缩略图的大小(kb)
*/
private Integer thumbnailSize = 60;
/**
* OpenOffice的安装目录
*/
private String openOfficeHome;
/**
* swagger扫描包
*/
private String swaggerBasePackage;
/**
* swagger文档标题
*/
private String swaggerTitle;
/**
* swagger文档描述
*/
private String swaggerDescription;
/**
* swagger文档版本号
*/
private String swaggerVersion;
/**
* swagger地址
*/
private String swaggerHost;
/**
* token过期时间, 单位秒
*/
private Long tokenExpireTime = 60 * 60 * 24L;
/**
* token快要过期自动刷新时间, 单位分钟
*/
private int tokenRefreshTime = 30;
/**
* 生成token的密钥Key的base64字符
*/
private String tokenKey;
}

View File

@ -0,0 +1,77 @@
package com.eleadmin.common.core.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.eleadmin.common.system.entity.User;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.NullValue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import java.util.Arrays;
/**
* MybatisPlus配置
*
* @author EleAdmin
* @since 2018-02-22 11:29:28
*/
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 多租户插件配置
TenantLineHandler tenantLineHandler = new TenantLineHandler() {
@Override
public Expression getTenantId() {
return getLoginUserTenantId();
}
@Override
public boolean ignoreTable(String tableName) {
return Arrays.asList(
"sys_tenant",
"sys_dictionary",
"sys_dictionary_data","t_distribution_device_info","t_outage_work","t_power_debug","t_fa_line","f_flow","f_step","f_field","f_step_table","f_step_table_field"
).contains(tableName);
}
};
TenantLineInnerInterceptor tenantLineInnerInterceptor = new TenantLineInnerInterceptor(tenantLineHandler);
interceptor.addInnerInterceptor(tenantLineInnerInterceptor);
// 分页插件配置
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
/**
* 获取当前登录用户的租户id
*
* @return Integer
*/
public Expression getLoginUserTenantId() {
try {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) {
Object object = authentication.getPrincipal();
if (object instanceof User) {
return new LongValue(((User) object).getTenantId());
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
return new NullValue();
}
}

View File

@ -0,0 +1,72 @@
package com.eleadmin.common.core.config;
import cn.hutool.core.util.StrUtil;
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 javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
/**
* Swagger配置
*
* @author EleAdmin
* @since 2018-02-22 11:29:05
*/
@EnableOpenApi
@Configuration
public class SwaggerConfig {
@Resource
private ConfigProperties config;
@Bean
public Docket createRestApi() {
Docket docket = new Docket(DocumentationType.OAS_30);
if (StrUtil.isNotBlank(config.getSwaggerHost())) {
docket.host(config.getSwaggerHost());
}
return docket
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage(config.getSwaggerBasePackage()))
.paths(PathSelectors.any())
.build()
.securitySchemes(securitySchemes())
.securityContexts(securityContexts());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(config.getSwaggerTitle())
.description(config.getSwaggerDescription())
.version(config.getSwaggerVersion())
.termsOfServiceUrl("")
.build();
}
private List<SecurityScheme> securitySchemes() {
return Collections.singletonList(
new ApiKey("Authorization", "Authorization", "header")
);
}
private List<SecurityContext> securityContexts() {
AuthorizationScope[] scopes = {new AuthorizationScope("global", "accessEverything")};
List<SecurityReference> references = Collections.singletonList(
new SecurityReference("Authorization", scopes)
);
return Collections.singletonList(SecurityContext.builder()
.securityReferences(references)
.build());
}
}

View File

@ -0,0 +1,31 @@
package com.eleadmin.common.core.config;
import com.eleadmin.common.core.Constants;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* WebMvc配置, 拦截器资源映射等都在此配置
*
* @author EleAdmin
* @since 2019-06-12 10:11:16
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
/**
* 支持跨域访问
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedHeaders("*")
.exposedHeaders(Constants.TOKEN_HEADER_NAME)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH")
.allowCredentials(true)
.maxAge(3600);
}
}

View File

@ -0,0 +1,20 @@
package com.eleadmin.common.core.excel.convert;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ReadConverterContext;
import java.time.LocalDateTime;
import static cn.hutool.core.date.LocalDateTimeUtil.parse;
public class LocalDateTimeConverter implements Converter<LocalDateTime> {
@Override
public Class<?> supportJavaTypeKey() {
return LocalDateTime.class; // 指定要转换的 Java 类型
}
@Override
public LocalDateTime convertToJavaData(ReadConverterContext<?> context) {
// 实现从 Excel 单元格数据到 Java 对象的转换逻辑
return parse(context.getReadCellData().getStringValue());
}
}

View File

@ -0,0 +1,32 @@
package com.eleadmin.common.core.excel.convert;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ReadConverterContext;
import com.alibaba.excel.converters.WriteConverterContext;
import com.alibaba.excel.metadata.data.WriteCellData;
public class YesNoConverter implements Converter<Integer> {
@Override
public Class<Integer> supportJavaTypeKey() {
return Integer.class;
}
@Override
public Integer convertToJavaData(ReadConverterContext<?> context) {
String description = context.getReadCellData().getStringValue();
if ("".equals(description)) {
return 1;
} else if ("".equals(description)) {
return 0;
} else {
throw new IllegalArgumentException("Invalid value for isPowerOutage: " + description);
}
}
@Override
public WriteCellData<?> convertToExcelData(WriteConverterContext<Integer> context) {
return new WriteCellData<>(context.getValue() == 1 ? "" : "");
}
}

View File

@ -0,0 +1,48 @@
package com.eleadmin.common.core.exception;
import com.eleadmin.common.core.Constants;
/**
* 自定义业务异常
*
* @author EleAdmin
* @since 2018-02-22 11:29:28
*/
public class BusinessException extends RuntimeException {
private static final long serialVersionUID = 1L;
private Integer code;
public BusinessException() {
this(Constants.RESULT_ERROR_MSG);
}
public BusinessException(String message) {
this(Constants.RESULT_ERROR_CODE, message);
}
public BusinessException(Integer code, String message) {
super(message);
this.code = code;
}
public BusinessException(Integer code, String message, Throwable cause) {
super(message, cause);
this.code = code;
}
public BusinessException(Integer code, String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
this.code = code;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
}

View File

@ -0,0 +1,56 @@
package com.eleadmin.common.core.exception;
import com.eleadmin.common.core.Constants;
import com.eleadmin.common.core.utils.CommonUtil;
import com.eleadmin.common.core.web.ApiResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
/**
* 全局异常处理器
*
* @author EleAdmin
* @since 2018-02-22 11:29:30
*/
@ControllerAdvice
public class GlobalExceptionHandler {
private final Logger logger = LoggerFactory.getLogger(getClass());
@ResponseBody
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public ApiResult<?> methodNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException e,
HttpServletResponse response) {
CommonUtil.addCrossHeaders(response);
return new ApiResult<>(Constants.RESULT_ERROR_CODE, "请求方式不正确").setError(e.toString());
}
@ResponseBody
@ExceptionHandler(AccessDeniedException.class)
public ApiResult<?> accessDeniedExceptionHandler(AccessDeniedException e, HttpServletResponse response) {
CommonUtil.addCrossHeaders(response);
return new ApiResult<>(Constants.UNAUTHORIZED_CODE, Constants.UNAUTHORIZED_MSG).setError(e.toString());
}
@ResponseBody
@ExceptionHandler(BusinessException.class)
public ApiResult<?> businessExceptionHandler(BusinessException e, HttpServletResponse response) {
CommonUtil.addCrossHeaders(response);
return new ApiResult<>(e.getCode(), e.getMessage());
}
@ResponseBody
@ExceptionHandler(Throwable.class)
public ApiResult<?> exceptionHandler(Throwable e, HttpServletResponse response) {
logger.error(e.getMessage(), e);
CommonUtil.addCrossHeaders(response);
return new ApiResult<>(Constants.RESULT_ERROR_CODE, Constants.RESULT_ERROR_MSG).setError(e.toString());
}
}

View File

@ -0,0 +1,29 @@
package com.eleadmin.common.core.security;
import com.eleadmin.common.core.Constants;
import com.eleadmin.common.core.utils.CommonUtil;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 没有访问权限异常处理
*
* @author EleAdmin
* @since 2020-03-25 00:35:03
*/
@Component
public class JwtAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e)
throws IOException, ServletException {
CommonUtil.responseError(response, Constants.UNAUTHORIZED_CODE, Constants.UNAUTHORIZED_MSG, e.getMessage());
}
}

View File

@ -0,0 +1,30 @@
package com.eleadmin.common.core.security;
import com.eleadmin.common.core.Constants;
import com.eleadmin.common.core.utils.CommonUtil;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 没有登录异常处理
*
* @author EleAdmin
* @since 2020-03-25 00:35:03
*/
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e)
throws IOException, ServletException {
CommonUtil.responseError(response, Constants.UNAUTHENTICATED_CODE, Constants.UNAUTHENTICATED_MSG,
e.getMessage());
}
}

View File

@ -0,0 +1,85 @@
package com.eleadmin.common.core.security;
import cn.hutool.core.util.StrUtil;
import com.eleadmin.common.core.Constants;
import com.eleadmin.common.core.config.ConfigProperties;
import com.eleadmin.common.core.utils.CommonUtil;
import com.eleadmin.common.system.entity.LoginRecord;
import com.eleadmin.common.system.entity.Menu;
import com.eleadmin.common.system.entity.User;
import com.eleadmin.common.system.service.LoginRecordService;
import com.eleadmin.common.system.service.UserService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* 处理携带token的请求过滤器
*
* @author EleAdmin
* @since 2020-03-30 20:48:05
*/
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Resource
private ConfigProperties configProperties;
@Resource
private UserService userService;
@Resource
private LoginRecordService loginRecordService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String access_token = JwtUtil.getAccessToken(request);
if (StrUtil.isNotBlank(access_token)) {
try {
// 解析token
Claims claims = JwtUtil.parseToken(access_token, configProperties.getTokenKey());
JwtSubject jwtSubject = JwtUtil.getJwtSubject(claims);
User user = userService.getByUsername(jwtSubject.getUsername(), jwtSubject.getTenantId());
if (user == null) {
throw new UsernameNotFoundException("Username not found");
}
List<Menu> authorities = user.getAuthorities().stream()
.filter(m -> StrUtil.isNotBlank(m.getAuthority())).collect(Collectors.toList());
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
user, null, authorities);
SecurityContextHolder.getContext().setAuthentication(authentication);
// token将要过期签发新token, 防止突然退出登录
long expiration = (claims.getExpiration().getTime() - new Date().getTime()) / 1000 / 60;
if (expiration < configProperties.getTokenRefreshTime()) {
String token = JwtUtil.buildToken(jwtSubject, configProperties.getTokenExpireTime(),
configProperties.getTokenKey());
response.addHeader(Constants.TOKEN_HEADER_NAME, token);
loginRecordService.saveAsync(user.getUsername(), LoginRecord.TYPE_REFRESH, null,
user.getTenantId(), request);
}
} catch (ExpiredJwtException e) {
CommonUtil.responseError(response, Constants.TOKEN_EXPIRED_CODE, Constants.TOKEN_EXPIRED_MSG,
e.getMessage());
return;
} catch (Exception e) {
CommonUtil.responseError(response, Constants.BAD_CREDENTIALS_CODE, Constants.BAD_CREDENTIALS_MSG,
e.toString());
return;
}
}
chain.doFilter(request, response);
}
}

View File

@ -0,0 +1,31 @@
package com.eleadmin.common.core.security;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* Jwt载体
*
* @author EleAdmin
* @since 2021-09-03 00:11:12
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class JwtSubject implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 账号
*/
private String username;
/**
* 租户id
*/
private Integer tenantId;
}

View File

@ -0,0 +1,141 @@
package com.eleadmin.common.core.security;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.eleadmin.common.core.Constants;
import com.eleadmin.common.core.utils.JSONUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.io.Encoders;
import io.jsonwebtoken.security.Keys;
import javax.servlet.http.HttpServletRequest;
import java.security.Key;
import java.util.Date;
/**
* JWT工具类
*
* @author EleAdmin
* @since 2018-01-21 16:30:59
*/
public class JwtUtil {
/**
* 获取请求中的access_token
*
* @param request HttpServletRequest
* @return String
*/
public static String getAccessToken(HttpServletRequest request) {
String access_token = ServletUtil.getHeaderIgnoreCase(request, Constants.TOKEN_HEADER_NAME);
if (StrUtil.isNotBlank(access_token)) {
if (access_token.startsWith(Constants.TOKEN_TYPE)) {
access_token = StrUtil.removePrefix(access_token, Constants.TOKEN_TYPE).trim();
}
} else {
access_token = request.getParameter(Constants.TOKEN_PARAM_NAME);
}
return access_token;
}
/**
* 生成token
*
* @param subject 载体
* @param expire 过期时间
* @param base64EncodedKey base64编码的Key
* @return token
*/
public static String buildToken(JwtSubject subject, Long expire, String base64EncodedKey) {
return buildToken(JSONUtil.toJSONString(subject), expire, decodeKey(base64EncodedKey));
}
/**
* 生成token
*
* @param subject 载体
* @param expire 过期时间
* @param key 密钥
* @return token
*/
public static String buildToken(String subject, Long expire, Key key) {
Date expireDate = new Date(new Date().getTime() + 1000 * expire);
return Jwts.builder()
.setSubject(subject)
.setExpiration(expireDate)
.setIssuedAt(new Date())
.signWith(key)
.compact();
}
/**
* 解析token
*
* @param token token
* @param base64EncodedKey base64编码的Key
* @return Claims
*/
public static Claims parseToken(String token, String base64EncodedKey) {
return parseToken(token, decodeKey(base64EncodedKey));
}
/**
* 解析token
*
* @param token token
* @param key 密钥
* @return Claims
*/
public static Claims parseToken(String token, Key key) {
return Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(token)
.getBody();
}
/**
* 获取JwtSubject
*
* @param claims Claims
* @return JwtSubject
*/
public static JwtSubject getJwtSubject(Claims claims) {
return JSONUtil.parseObject(claims.getSubject(), JwtSubject.class);
}
/**
* 生成Key
*
* @return Key
*/
public static Key randomKey() {
return Keys.secretKeyFor(SignatureAlgorithm.HS256);
}
/**
* base64编码key
*
* @return String
*/
public static String encodeKey(Key key) {
return Encoders.BASE64.encode(key.getEncoded());
}
/**
* base64编码Key
*
* @param base64EncodedKey base64编码的key
* @return Key
*/
public static Key decodeKey(String base64EncodedKey) {
if (StrUtil.isBlank(base64EncodedKey)) {
return null;
}
return Keys.hmacShaKeyFor(Decoders.BASE64.decode(base64EncodedKey));
}
}

View File

@ -0,0 +1,80 @@
package com.eleadmin.common.core.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.annotation.Resource;
/**
* Spring Security配置
*
* @author EleAdmin
* @since 2020-03-23 18:04:52
*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private JwtAccessDeniedHandler jwtAccessDeniedHandler;
@Resource
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Resource
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**")
.permitAll()
.antMatchers(HttpMethod.GET, "/api/file/**", "/api/captcha", "/")
.permitAll()
.antMatchers(
"/api/login",
"/druid/**",
"/swagger-ui.html",
"/swagger-resources/**",
"/webjars/**",
"/v2/api-docs",
"/res/**",
"/v3/api-docs",
"/swagger-ui/**"
)
.permitAll()
.anyRequest()
.authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf()
.disable()
.cors()
.and()
.logout()
.disable()
.headers()
.frameOptions()
.disable()
.and()
.exceptionHandling()
.accessDeniedHandler(jwtAccessDeniedHandler)
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and()
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}

View File

@ -0,0 +1,15 @@
package com.eleadmin.common.core.utils;
import java.math.BigDecimal;
public class BigdecimalUnit {
public static String bigDecimalToString(BigDecimal num) {
if (num == null) return null;
String str = num.stripTrailingZeros().toPlainString();
if (str.contains(".")) {
str = str.replaceAll("\\.?0+$", "");
}
return str;
}
}

View File

@ -0,0 +1,174 @@
package com.eleadmin.common.core.utils;
import cn.hutool.core.util.ObjectUtil;
import com.eleadmin.common.core.Constants;
import com.eleadmin.common.core.web.ApiResult;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* 常用工具方法
*
* @author EleAdmin
* @since 2017-06-10 10:10:22
*/
public class CommonUtil {
// 生成uuid的字符
private static final String[] chars = new String[]{
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
};
/**
* 生成8位uuid
*
* @return String
*/
public static String randomUUID8() {
StringBuilder sb = new StringBuilder();
String uuid = UUID.randomUUID().toString().replace("-", "");
for (int i = 0; i < 8; i++) {
String str = uuid.substring(i * 4, i * 4 + 4);
int x = Integer.parseInt(str, 16);
sb.append(chars[x % 0x3E]);
}
return sb.toString();
}
/**
* 生成16位uuid
*
* @return String
*/
public static String randomUUID16() {
StringBuilder sb = new StringBuilder();
String uuid = UUID.randomUUID().toString().replace("-", "");
for (int i = 0; i < 16; i++) {
String str = uuid.substring(i * 2, i * 2 + 2);
int x = Integer.parseInt(str, 16);
sb.append(chars[x % 0x3E]);
}
return sb.toString();
}
/**
* 检查List是否有重复元素
*
* @param list List
* @param mapper 获取需要检查的字段的Function
* @param <T> 数据的类型
* @param <R> 需要检查的字段的类型
* @return boolean
*/
public static <T, R> boolean checkRepeat(List<T> list, Function<? super T, ? extends R> mapper) {
for (int i = 0; i < list.size(); i++) {
for (int j = 0; j < list.size(); j++) {
if (i != j && mapper.apply(list.get(i)).equals(mapper.apply(list.get(j)))) {
return true;
}
}
}
return false;
}
/**
* List转为树形结构
*
* @param data List
* @param parentId 顶级的parentId
* @param parentIdMapper 获取parentId的Function
* @param idMapper 获取id的Function
* @param consumer 赋值children的Consumer
* @param <T> 数据的类型
* @param <R> parentId的类型
* @return List<T>
*/
public static <T, R> List<T> toTreeData(List<T> data, R parentId,
Function<? super T, ? extends R> parentIdMapper,
Function<? super T, ? extends R> idMapper,
BiConsumer<T, List<T>> consumer) {
List<T> result = new ArrayList<>();
for (T d : data) {
R dParentId = parentIdMapper.apply(d);
if (ObjectUtil.equals(parentId, dParentId)) {
R dId = idMapper.apply(d);
List<T> children = toTreeData(data, dId, parentIdMapper, idMapper, consumer);
consumer.accept(d, children);
result.add(d);
}
}
return result;
}
/**
* 遍历树形结构数据
*
* @param data List
* @param consumer 回调
* @param mapper 获取children的Function
* @param <T> 数据的类型
*/
public static <T> void eachTreeData(List<T> data, Consumer<T> consumer, Function<T, List<T>> mapper) {
for (T d : data) {
consumer.accept(d);
List<T> children = mapper.apply(d);
if (children != null && children.size() > 0) {
eachTreeData(children, consumer, mapper);
}
}
}
/**
* 获取集合中的第一条数据
*
* @param records 集合
* @return 第一条数据
*/
public static <T> T listGetOne(List<T> records) {
return records == null || records.size() == 0 ? null : records.get(0);
}
/**
* 支持跨域
*
* @param response HttpServletResponse
*/
public static void addCrossHeaders(HttpServletResponse response) {
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Expose-Headers", Constants.TOKEN_HEADER_NAME);
}
/**
* 输出错误信息
*
* @param response HttpServletResponse
* @param code 错误码
* @param message 提示信息
* @param error 错误信息
*/
public static void responseError(HttpServletResponse response, Integer code, String message, String error) {
response.setContentType("application/json;charset=UTF-8");
try {
PrintWriter out = response.getWriter();
out.write(JSONUtil.toJSONString(new ApiResult<>(code, message, null, error)));
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,95 @@
package com.eleadmin.common.core.utils;
import cn.hutool.core.bean.BeanUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream;
import org.springframework.beans.BeanUtils;
import org.springframework.util.ResourceUtils;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class ExcelExportEngine {
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
public static Workbook writeToExcel(Object object, Workbook workbook,String photoPath) throws Exception{
//先把bean转成map这个Object表示对象也就是bean
Map<String, Object> map = BeanUtil.beanToMap(object);
//循环遍历每一对数据,把日期型的转成字符串方便导出
for (String key : map.keySet()) {
Object vlaue = map.get(key);
if(vlaue instanceof Date){
System.out.println(sdf.format(vlaue));
map.put(key,sdf.format(vlaue));
}
}
//获取第一个sheet整体的思路是循环100个行的100个单元格
Sheet sheet = workbook.getSheetAt(0);
Cell cell =null;
Row row = null;
for (int i = 0; i < 100; i++) {
row = sheet.getRow(i); //获取到空行为止
if(row==null){
break;
}else{
for (int j = 0; j < 100; j++) {
cell = row.getCell(j);//获取到空单元格不处理
if(cell!=null){
writeCell(cell,map); //开始向单元格中写内容
}
}
}
}
if(StringUtils.isNotBlank(photoPath)){
File rootPath = new File(ResourceUtils.getURL("classpath:").getPath()); //SpringBoot项目获取根目录的方式
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
// BufferedImage是一个带缓冲区图像类,主要作用是将一幅图片加载到内存中
BufferedImage bufferImg = ImageIO
.read(new File(rootPath + photoPath));
ImageIO.write(bufferImg, "jpg", byteArrayOut);
Drawing patriarch = sheet.createDrawingPatriarch();
Sheet sheet2 = workbook.getSheetAt(1);
row = sheet2.getRow(0);
int col1 = ((Double) row.getCell(0).getNumericCellValue()).intValue();
int row1 = ((Double) row.getCell(1).getNumericCellValue()).intValue();
int col2 = ((Double) row.getCell(2).getNumericCellValue()).intValue();
int row2 = ((Double) row.getCell(3).getNumericCellValue()).intValue();
// 锚点固定点
ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, col1, row1, col2, row2);
patriarch.createPicture(anchor, workbook.addPicture(byteArrayOut.toByteArray(), Workbook.PICTURE_TYPE_JPEG));
workbook.removeSheetAt(1);
}
return workbook;
}
private static void writeCell(Cell cell, Map<String, Object> map) {
CellType cellType = cell.getCellType();
switch (cellType){
case FORMULA:{ //如果是公式就直接放行了
break;
}default:{
String cellValue = cell.getStringCellValue();
//就是判断一下获取到单元格中的值是否和map中的key保持一致
if(StringUtils.isNotBlank(cellValue)){
for (String key : map.keySet()) {
if(key.equals(cellValue)){
cell.setCellValue(map.get(key) == null ? "" :map.get(key).toString());
}
}
}
}
}
}
}

View File

@ -0,0 +1,98 @@
package com.eleadmin.common.core.utils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.channels.ClosedChannelException;
import java.util.*;
public class ExcelMapReader {
/**
* 读取所有Sheet数据返回结构Map<Sheet名称, List<行数据Map>>
*/
public Map<String, List<Map<String, Object>>> readAllSheets(File file) throws IOException {
// 存储最终结果Key=Sheet名称Value=该Sheet的数据列表
Map<String, List<Map<String, Object>>> result = new LinkedHashMap<>();
try{
FileInputStream fileInputStream = new FileInputStream(file);
// 1. 获取所有Sheet信息
List<ReadSheet> sheets = EasyExcel.read(fileInputStream).excelType(ExcelTypeEnum.XLS)
.build()
.excelExecutor()
.sheetList();
fileInputStream.close();
// 2. 遍历每个Sheet读取数据
for (ReadSheet sheet : sheets) {
// 每个Sheet的数据监听器
SheetDataListener listener = new SheetDataListener();
FileInputStream fileInputStream1 = new FileInputStream(file);
// 读取当前Sheet指定sheetNo和标题行
EasyExcel.read(fileInputStream1).excelType(ExcelTypeEnum.XLS)
.headRowNumber(1) // 假设第一行为标题行
.sheet(sheet.getSheetNo())
.registerReadListener(listener)
.doRead();
fileInputStream1.close();
// 将当前Sheet数据存入结果
result.put(sheet.getSheetName(), listener.getDataList());
}
}catch (ExcelAnalysisException e) {
Throwable cause = e.getCause();
if (cause instanceof ClosedChannelException) {
// 处理流关闭问题
System.err.println("流已关闭:" + cause.getMessage());
}
}
return result;
}
/**
* 自定义Sheet数据监听器
*/
private static class SheetDataListener implements ReadListener<Map<Integer, String>> {
private List<Map<String, Object>> dataList = new ArrayList<>();
private Map<Integer, ReadCellData<?>> headerMap; // 存储列索引与标题的映射
@Override
public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
// 读取标题行第一行
this.headerMap = headMap;
}
@Override
public void invoke(Map<Integer, String> rowData, AnalysisContext context) {
// 将索引映射的RowData转换为标题键的Map
Map<String, Object> rowMap = new HashMap<>();
for (Map.Entry<Integer, String> entry : rowData.entrySet()) {
String header = headerMap.get(entry.getKey()).getStringValue();
rowMap.put(header, entry.getValue());
}
dataList.add(rowMap);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 可在此处添加数据校验或后处理
}
public List<Map<String, Object>> getDataList() {
return dataList;
}
}
}

View File

@ -0,0 +1,394 @@
package com.eleadmin.common.core.utils;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import org.apache.tika.Tika;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* 文件上传下载工具类
*
* @author EleAdmin
* @since 2018-12-14 08:38:53
*/
public class FileServerUtil {
// text/* 外也需要设置输出编码的 content-type
private final static List<String> SET_CHARSET_CONTENT_TYPES = Arrays.asList(
"application/json",
"application/javascript"
);
/**
* 上传文件
*
* @param file MultipartFile
* @param directory 文件保存的目录
* @param uuidName 是否用uuid命名
* @return File
*/
public static File upload(MultipartFile file, String directory, boolean uuidName)
throws IOException, IllegalStateException {
File outFile = getUploadFile(file.getOriginalFilename(), directory, uuidName);
if (!outFile.getParentFile().exists()) {
if (!outFile.getParentFile().mkdirs()) {
throw new RuntimeException("make directory fail");
}
}
file.transferTo(outFile);
return outFile;
}
/**
* 上传base64格式文件
*
* @param base64 base64编码字符
* @param fileName 文件名称, 为空使用uuid命名
* @param directory 文件保存的目录
* @return File
*/
public static File upload(String base64, String fileName, String directory)
throws FileNotFoundException, IORuntimeException {
if (StrUtil.isBlank(base64) || !base64.startsWith("data:image/") || !base64.contains(";base64,")) {
throw new RuntimeException("base64 data error");
}
String suffix = "." + base64.substring(11, base64.indexOf(";")); // 获取文件后缀
boolean uuidName = StrUtil.isBlank(fileName);
File outFile = getUploadFile(uuidName ? suffix : fileName, directory, uuidName);
byte[] bytes = Base64.getDecoder().decode(base64.substring(base64.indexOf(";") + 8).getBytes());
IoUtil.write(new FileOutputStream(outFile), true, bytes);
return outFile;
}
/**
* 获取上传文件位置
*
* @param name 文件名称
* @param directory 上传目录
* @param uuidName 是否使用uuid命名
* @return File
*/
public static File getUploadFile(String name, String directory, boolean uuidName) {
// 当前日期作为上传子目录
String dir = new SimpleDateFormat("yyyyMMdd/").format(new Date());
// 获取文件后缀
String suffix = (name == null || !name.contains(".")) ? "" : name.substring(name.lastIndexOf("."));
// 使用uuid命名
if (uuidName || name == null) {
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
return new File(directory, dir + uuid + suffix);
}
// 使用原名称, 存在相同则加(1)
File file = new File(directory, dir + name);
String prefix = StrUtil.removeSuffix(name, suffix);
int sameSize = 2;
while (file.exists()) {
file = new File(directory, dir + prefix + "(" + sameSize + ")" + suffix);
sameSize++;
}
return file;
}
/**
* 查看文件, 支持断点续传
*
* @param file 文件
* @param pdfDir office转pdf输出目录
* @param officeHome openOffice安装目录
* @param response HttpServletResponse
* @param request HttpServletRequest
*/
public static void preview(File file, String pdfDir, String officeHome,
HttpServletResponse response, HttpServletRequest request) {
preview(file, false, null, pdfDir, officeHome, response, request);
}
/**
* 查看文件, 支持断点续传
*
* @param file 文件
* @param forceDownload 是否强制下载
* @param fileName 强制下载的文件名称
* @param pdfDir office转pdf输出目录
* @param officeHome openOffice安装目录
* @param response HttpServletResponse
* @param request HttpServletRequest
*/
public static void preview(File file, boolean forceDownload, String fileName, String pdfDir, String officeHome,
HttpServletResponse response, HttpServletRequest request) {
CommonUtil.addCrossHeaders(response);
if (file == null || !file.exists()) {
outNotFund(response);
return;
}
if (forceDownload) {
setDownloadHeader(response, StrUtil.isBlank(fileName) ? file.getName() : fileName);
} else {
// office转pdf预览
if (OpenOfficeUtil.canConverter(file.getName())) {
File pdfFile = OpenOfficeUtil.converterToPDF(file.getAbsolutePath(), pdfDir, officeHome);
if (pdfFile != null) {
file = pdfFile;
}
}
// 获取文件类型
String contentType = getContentType(file);
if (contentType != null) {
response.setContentType(contentType);
// 设置编码
if (contentType.startsWith("text/") || SET_CHARSET_CONTENT_TYPES.contains(contentType)) {
try {
String charset = JChardetFacadeUtil.detectCodepage(file.toURI().toURL());
if (charset != null) {
response.setCharacterEncoding(charset);
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
} else {
setDownloadHeader(response, file.getName());
}
}
response.setHeader("Cache-Control", "public");
output(file, response, request);
}
/**
* 查看缩略图
*
* @param file 原文件
* @param thumbnail 缩略图文件
* @param size 缩略图文件的最大值(kb)
* @param response HttpServletResponse
* @param request HttpServletRequest
*/
public static void previewThumbnail(File file, File thumbnail, Integer size,
HttpServletResponse response, HttpServletRequest request) {
// 如果是图片并且缩略图不存在则生成
if (!thumbnail.exists() && isImage(file)) {
long fileSize = file.length();
if ((fileSize / 1024) > size) {
try {
if (thumbnail.getParentFile().mkdirs()) {
ImgUtil.scale(file, thumbnail, size / (fileSize / 1024f));
if (thumbnail.exists() && thumbnail.length() > file.length()) {
FileUtil.copy(file, thumbnail, true);
}
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
preview(file, null, null, response, request);
return;
}
}
preview(thumbnail.exists() ? thumbnail : file, null, null, response, request);
}
/**
* 输出文件流, 支持断点续传
*
* @param file 文件
* @param response HttpServletResponse
* @param request HttpServletRequest
*/
public static void output(File file, HttpServletResponse response, HttpServletRequest request) {
long length = file.length(); // 文件总大小
long start = 0, to = length - 1; // 开始读取位置, 结束读取位置
long lastModified = file.lastModified(); // 文件修改时间
response.setHeader("Accept-Ranges", "bytes");
response.setHeader("ETag", "\"" + length + "-" + lastModified + "\"");
response.setHeader("Last-Modified", new Date(lastModified).toString());
String range = request.getHeader("Range");
if (range != null) {
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
String[] ranges = range.replace("bytes=", "").split("-");
start = Long.parseLong(ranges[0].trim());
if (ranges.length > 1) {
to = Long.parseLong(ranges[1].trim());
}
response.setHeader("Content-Range", "bytes " + start + "-" + to + "/" + length);
}
response.setHeader("Content-Length", String.valueOf(to - start + 1));
try {
output(file, response.getOutputStream(), 2048, start, to);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 输出文件流
*
* @param file 文件
* @param os 输出流
*/
public static void output(File file, OutputStream os) {
output(file, os, null);
}
/**
* 输出文件流
*
* @param file 文件
* @param os 输出流
* @param size 读取缓冲区大小
*/
public static void output(File file, OutputStream os, Integer size) {
output(file, os, size, null, null);
}
/**
* 输出文件流, 支持分片
*
* @param file 文件
* @param os 输出流
* @param size 读取缓冲区大小
* @param start 开始位置
* @param to 结束位置
*/
public static void output(File file, OutputStream os, Integer size, Long start, Long to) {
BufferedInputStream is = null;
try {
is = new BufferedInputStream(new FileInputStream(file));
if (start != null) {
long skip = is.skip(start);
if (skip < start) {
System.out.println("ERROR: skip fail[ skipped=" + skip + ", start= " + start + " ]");
}
to = to - start + 1;
}
byte[] bytes = new byte[size == null ? 2048 : size];
int len;
if (to == null) {
while ((len = is.read(bytes)) != -1) {
os.write(bytes, 0, len);
}
} else {
while (to > 0 && (len = is.read(bytes)) != -1) {
os.write(bytes, 0, to < len ? (int) ((long) to) : len);
to -= len;
}
}
os.flush();
} catch (IOException ignored) {
} catch (Exception e) {
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException ignored) {
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
}
/**
* 获取文件类型
*
* @param file 文件
* @return String
*/
public static String getContentType(File file) {
String contentType = null;
if (file.exists()) {
try {
contentType = new Tika().detect(file);
} catch (IOException e) {
e.printStackTrace();
}
}
return contentType;
}
/**
* 判断文件是否是图片类型
*
* @param file 文件
* @return boolean
*/
public static boolean isImage(File file) {
return isImage(getContentType(file));
}
/**
* 判断文件是否是图片类型
*
* @param contentType 文件类型
* @return boolean
*/
public static boolean isImage(String contentType) {
return contentType != null && contentType.startsWith("image/");
}
/**
* 设置下载文件的header
*
* @param response HttpServletResponse
* @param fileName 文件名称
*/
public static void setDownloadHeader(HttpServletResponse response, String fileName) {
response.setContentType("application/force-download");
try {
fileName = URLEncoder.encode(fileName, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
}
/**
* 输出404错误页面
*
* @param response HttpServletResponse
*/
public static void outNotFund(HttpServletResponse response) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
outMessage("404 Not Found", null, response);
}
/**
* 输出错误页面
*
* @param title 标题
* @param message 内容
* @param response HttpServletResponse
*/
public static void outMessage(String title, String message, HttpServletResponse response) {
response.setContentType("text/html;charset=UTF-8");
try {
PrintWriter writer = response.getWriter();
writer.write("<!doctype html>");
writer.write("<title>" + title + "</title>");
writer.write("<h1 style=\"text-align: center\">" + title + "</h1>");
if (message != null) {
writer.write(message);
}
writer.write("<hr/><p style=\"text-align: center\">EleAdmin File Server</p>");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,69 @@
package com.eleadmin.common.core.utils;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
/**
* JSON解析工具类
*
* @author EleAdmin
* @since 2017-06-10 10:10:39
*/
public class JSONUtil {
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final ObjectWriter objectWriter = objectMapper.writerWithDefaultPrettyPrinter();
/**
* 对象转json字符串
*
* @param value 对象
* @return String
*/
public static String toJSONString(Object value) {
return toJSONString(value, false);
}
/**
* 对象转json字符串
*
* @param value 对象
* @param pretty 是否格式化输出
* @return String
*/
public static String toJSONString(Object value, boolean pretty) {
if (value != null) {
if (value instanceof String) {
return (String) value;
}
try {
if (pretty) {
return objectWriter.writeValueAsString(value);
}
return objectMapper.writeValueAsString(value);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* json字符串转对象
*
* @param json String
* @param clazz Class
* @return T
*/
public static <T> T parseObject(String json, Class<T> clazz) {
if (StrUtil.isNotBlank(json) && clazz != null) {
try {
return objectMapper.readValue(json, clazz);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}

View File

@ -0,0 +1,95 @@
package com.eleadmin.common.core.utils;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class LocalCache {
/**
* 预缓存信息
*/
private static final Map<String, Object> CACHE_MAP = new ConcurrentHashMap<>(16);
/**
* 存放一个缓存对象默认保存时间半小时
* @param cacheName
* @param obj
*/
public static void put(String cacheName, Object obj) {
put(cacheName, obj, 60 * 60 / 2L);
}
/**
* 存放一个缓存对象保存时间为holdTime
* @param cacheName
* @param obj
* @param holdTime
*/
public static void put(String cacheName, Object obj, long holdTime) {
CACHE_MAP.put(cacheName, obj);
CACHE_MAP.put(cacheName + "_HoldTime", System.currentTimeMillis() + holdTime);//缓存失效时间
}
public static void put(String cacheName, Object obj, int holdTime) {
CACHE_MAP.put(cacheName, obj);
CACHE_MAP.put(cacheName + "_HoldTime", System.currentTimeMillis() + holdTime * 1000L);//缓存失效时间
}
/**
* 取出一个缓存对象
* @param cacheName
* @return
*/
public static Object get(String cacheName) {
if (checkCacheName(cacheName)) {
return CACHE_MAP.get(cacheName);
}
return null;
}
public static boolean containsKey(String cacheName) {
return checkCacheName(cacheName);
}
public static boolean isEmpty(String cacheName) {
return !checkCacheName(cacheName);
}
/**
* 删除所有缓存
*/
public static void removeAll() {
CACHE_MAP.clear();
}
/**
* 删除某个缓存
* @param cacheName
*/
public static void remove(String cacheName) {
CACHE_MAP.remove(cacheName);
CACHE_MAP.remove(cacheName + "_HoldTime");
}
/**
* 检查缓存对象是否存在
* 若不存在则返回false
* 若存在检查其是否已过有效期如果已经过了则删除该缓存并返回false
* @param cacheName
* @return
*/
public static boolean checkCacheName(String cacheName) {
Long cacheHoldTime = (Long) CACHE_MAP.get(cacheName + "_HoldTime");
if (cacheHoldTime == null || cacheHoldTime == 0L) {
remove(cacheName);
return false;
}
if (cacheHoldTime < System.currentTimeMillis()) {
remove(cacheName);
return false;
}
return true;
}
}

View File

@ -0,0 +1,124 @@
package com.eleadmin.common.core.utils;
import cn.hutool.core.util.StrUtil;
import org.artofsolving.jodconverter.OfficeDocumentConverter;
import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration;
import org.artofsolving.jodconverter.office.OfficeManager;
import java.io.File;
import java.util.Arrays;
import java.util.Base64;
/**
* OpenOfficeUtil
*
* @author EleAdmin
* @since 2018-12-14 08:38:19
*/
public class OpenOfficeUtil {
// 支持转换pdf的文件后缀列表
private static final String[] CAN_CONVERTER_FILES = new String[]{
"doc", "docx", "xls", "xlsx", "ppt", "pptx"
};
/**
* 文件转pdf
*
* @param filePath 源文件路径
* @param outDir 输出目录
* @param officeHome OpenOffice安装路径
* @return File
*/
public static File converterToPDF(String filePath, String outDir, String officeHome) {
return converterToPDF(filePath, outDir, officeHome, true);
}
/**
* 文件转pdf
*
* @param filePath 源文件路径
* @param outDir 输出目录
* @param officeHome OpenOffice安装路径
* @param cache 是否使用上次转换过的文件
* @return File
*/
public static File converterToPDF(String filePath, String outDir, String officeHome, boolean cache) {
if (StrUtil.isBlank(filePath)) {
return null;
}
File srcFile = new File(filePath);
if (!srcFile.exists()) {
return null;
}
// 是否转换过
String outPath = Base64.getEncoder().encodeToString(filePath.getBytes())
.replace("/", "-").replace("+", "-");
File outFile = new File(outDir, outPath + ".pdf");
if (cache && outFile.exists()) {
return outFile;
}
// 转换
OfficeManager officeManager = null;
try {
officeManager = getOfficeManager(officeHome);
OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager);
return converterFile(srcFile, outFile, converter);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (officeManager != null) {
officeManager.stop();
}
}
return null;
}
/**
* 转换文件
*
* @param inFile 源文件
* @param outFile 输出文件
* @param converter OfficeDocumentConverter
* @return File
*/
public static File converterFile(File inFile, File outFile, OfficeDocumentConverter converter) {
if (!outFile.getParentFile().exists()) {
if (!outFile.getParentFile().mkdirs()) {
return outFile;
}
}
converter.convert(inFile, outFile);
return outFile;
}
/**
* 判断文件后缀是否可以转换pdf
*
* @param path 文件路径
* @return boolean
*/
public static boolean canConverter(String path) {
try {
String suffix = path.substring(path.lastIndexOf(".") + 1);
return Arrays.asList(CAN_CONVERTER_FILES).contains(suffix);
} catch (Exception e) {
return false;
}
}
/**
* 连接并启动OpenOffice
*
* @param officeHome OpenOffice安装路径
* @return OfficeManager
*/
public static OfficeManager getOfficeManager(String officeHome) {
if (officeHome == null || officeHome.trim().isEmpty()) return null;
DefaultOfficeManagerConfiguration config = new DefaultOfficeManagerConfiguration();
config.setOfficeHome(officeHome); // 设置OpenOffice安装目录
OfficeManager officeManager = config.buildOfficeManager();
officeManager.start(); // 启动OpenOffice服务
return officeManager;
}
}

View File

@ -0,0 +1,94 @@
package com.eleadmin.common.core.utils;
import org.springframework.beans.BeanUtils;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* bean相关工具类
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2018-01-15 10:48:23
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
public class SmartBeanUtil {
/**
* 验证器
*/
private static final Validator VALIDATOR = Validation.buildDefaultValidatorFactory().getValidator();
/**
* 复制bean的属性
*
* @param source 要复制的对象
* @param target 目标 复制到此对象
*/
public static void copyProperties(Object source, Object target) {
BeanUtils.copyProperties(source, target);
}
/**
* 复制对象
*
* @param source 要复制的对象
* @param target 目标 复制到此对象
* @param <T>
* @return
*/
public static <T> T copy(Object source, Class<T> target) {
if (source == null || target == null) {
return null;
}
try {
T newInstance = target.getConstructor().newInstance();
BeanUtils.copyProperties(source, newInstance);
return newInstance;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 复制list
*
* @param source
* @param target
* @param <T>
* @param <K>
* @return
*/
public static <T, K> List<K> copyList(List<T> source, Class<K> target) {
if (null == source || source.isEmpty()) {
return Collections.emptyList();
}
return source.stream().map(e -> copy(e, target)).collect(Collectors.toList());
}
/**
* 手动验证对象 Model的属性
* 需要配合 hibernate-validator 校验注解
*
* @param t
* @return String 返回null代表验证通过否则返回错误的信息
*/
public static <T> String verify(T t) {
// 获取验证结果
Set<ConstraintViolation<T>> validate = VALIDATOR.validate(t);
if (validate.isEmpty()) {
// 验证通过
return null;
}
// 返回错误信息
List<String> messageList = validate.stream().map(ConstraintViolation::getMessage).toList();
return messageList.toString();
}
}

View File

@ -0,0 +1,306 @@
package com.eleadmin.common.core.utils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com.eleadmin.common.core.exception.BusinessException;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.xssf.usermodel.XSSFPictureData;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.stream.Collectors;
/**
* excel 工具类
*
* @Author 1024创新实验室-主任:卓大
* @Date 2024/4/22 22:49:07
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright 1024创新实验室 https://1024lab.net 2012-2024
*/
public final class SmartExcelUtil {
/**
* 通用单sheet导出
*/
public static void exportExcel(HttpServletResponse response, String fileName, String sheetName, Class head, Collection<?> data) throws IOException {
// 设置下载消息头
SmartResponseUtil.setDownloadFileHeader(response, fileName, null);
// 下载
EasyExcel.write(response.getOutputStream(), head)
.autoCloseStream(Boolean.FALSE)
.sheet(sheetName)
.doWrite(data);
}
/**
* 通用单 sheet水印 导出
*/
public static void exportExcelWithWatermark(HttpServletResponse response, String fileName, String sheetName, Class head, Collection<?> data, String watermarkString) throws IOException {
// 设置下载消息头
SmartResponseUtil.setDownloadFileHeader(response, fileName, null);
// 水印
Watermark watermark = new Watermark(watermarkString);
// 一定要inMemory
EasyExcel.write(response.getOutputStream(), head)
.inMemory(true)
.sheet(sheetName)
.registerWriteHandler(new CustomWaterMarkHandler(watermark))
.doWrite(data);
}
@Slf4j
private record CustomWaterMarkHandler(Watermark watermark) implements SheetWriteHandler {
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
BufferedImage bufferedImage = createWatermarkImage();
XSSFWorkbook workbook = (XSSFWorkbook) writeSheetHolder.getParentWriteWorkbookHolder().getWorkbook();
try {
// 添加水印的具体操作
addWatermarkToSheet(workbook, bufferedImage);
} catch (Exception e) {
log.error("添加水印出错:", e);
}
}
/**
* 创建水印图片
*
* @return BufferedImage
*/
private BufferedImage createWatermarkImage() {
// 获取水印相关参数
Font font = watermark.getFont();
int width = watermark.getWidth();
int height = watermark.getHeight();
Color color = watermark.getColor();
String text = watermark.getContent();
// 创建带有透明背景的 BufferedImage
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
// 设置画笔字体平滑颜色
g.setFont(font);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color);
// 计算水印位置和角度
int y = watermark.getYAxis();
int x = watermark.getXAxis();
AffineTransform transform = AffineTransform.getRotateInstance(Math.toRadians(-watermark.getAngle()), 0, y);
g.setTransform(transform);
// 绘制水印文字
g.drawString(text, x, y);
// 释放资源
g.dispose();
return image;
}
private void addWatermarkToSheet(XSSFWorkbook workbook, BufferedImage watermarkImage) {
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
ImageIO.write(watermarkImage, "png", os);
int pictureIdx = workbook.addPicture(os.toByteArray(), XSSFWorkbook.PICTURE_TYPE_PNG);
XSSFPictureData pictureData = workbook.getAllPictures().get(pictureIdx);
for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
// 获取每个Sheet表
XSSFSheet sheet = workbook.getSheetAt(i);
PackagePartName ppn = pictureData.getPackagePart().getPartName();
String relType = XSSFRelation.IMAGES.getRelation();
PackageRelationship pr = sheet.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null);
sheet.getCTWorksheet().addNewPicture().setId(pr.getId());
}
} catch (Exception e) {
// 处理ImageIO.write可能抛出的异常
log.error("添加水印图片时发生错误", e);
}
}
}
@Data
private static class Watermark {
public Watermark(String content) {
this.content = content;
init();
}
public Watermark(String content, Color color, Font font, double angle) {
this.content = content;
this.color = color;
this.font = font;
this.angle = angle;
init();
}
/**
* 根据水印内容长度自适应水印图片大小简单的三角函数
*/
private void init() {
FontMetrics fontMetrics = new JLabel().getFontMetrics(this.font);
int stringWidth = fontMetrics.stringWidth(this.content);
int charWidth = fontMetrics.charWidth('A');
this.width = (int) Math.abs(stringWidth * Math.cos(Math.toRadians(this.angle))) + 5 * charWidth;
this.height = (int) Math.abs(stringWidth * Math.sin(Math.toRadians(this.angle))) + 5 * charWidth;
this.yAxis = this.height;
this.xAxis = charWidth;
}
/**
* 水印内容
*/
private String content;
/**
* 画笔颜色
*/
private Color color = new Color(239, 239, 239);
/**
* 字体样式
*/
private Font font = new Font("Microsoft YaHei", Font.BOLD, 26);
/**
* 水印宽度
*/
private int width;
/**
* 水印高度
*/
private int height;
/**
* 倾斜角度非弧度制
*/
private double angle = 25;
/**
* 字体的y轴位置
*/
private int yAxis = 50;
/**
* 字体的X轴位置
*/
private int xAxis;
/**
* 水平倾斜度
*/
private double shearX = 0.1;
/**
* 垂直倾斜度
*/
private double shearY = -0.26;
}
/**
* 读取Excel文件并验证表头
*
* @param inputStream Excel文件输入流
* @param expectedHeaders 预期的表头
* @param dataClass Excel数据对应的类
* @param <T> 数据实体的类型
* @return 包含Excel数据的列表
*/
public static <T> java.util.List<T> readExcelWithHeaderValidation(InputStream inputStream, java.util.List<String> expectedHeaders, Class<T> dataClass) {
// 创建HeaderValidationListener实例
HeaderValidationListener<T> headerValidationListener = new HeaderValidationListener<>(expectedHeaders);
// 读取表头并验证 // 读取Excel数据
return EasyExcel.read(inputStream, dataClass, headerValidationListener).sheet().doReadSync();
}
/**
* 读取Excel文件并验证表头
*
* @param inputStream Excel文件输入流
* @param dataClass Excel数据对应的类
* @param <T> 数据实体的类型
* @return 包含Excel数据的列表
* @throws IOException 如果读取文件时发生IO异常
* @throws IllegalArgumentException 如果表头格式不正确
*/
public static <T> java.util.List<T> readExcelWithHeaderValidation(InputStream inputStream, Class<T> dataClass) throws IOException {
// 获取预期的表头
java.util.List<String> expectedHeaders = getExpectedHeaders(dataClass);
return readExcelWithHeaderValidation(inputStream, expectedHeaders, dataClass);
}
/**
* 获取预期的表头
*
* @param dataClass Excel数据对应的类
* @return 预期的表头列表
*/
private static <T> java.util.List<String> getExpectedHeaders(Class<T> dataClass) {
return java.util.Arrays.stream(dataClass.getDeclaredFields())
.filter(field -> field.isAnnotationPresent(ExcelProperty.class))
.map(field -> field.getAnnotation(ExcelProperty.class).value()[0])
.collect(Collectors.toList());
}
/**
* 自定义的ReadListener来读取表头并进行验证
*/
private static class HeaderValidationListener<T> extends AnalysisEventListener<T> {
private final java.util.List<String> expectedHeaders;
private final java.util.List<String> actualHeaders = new java.util.ArrayList<>();
private boolean headerRead = false;
public HeaderValidationListener(java.util.List<String> expectedHeaders) {
this.expectedHeaders = expectedHeaders;
}
@Override
public void invokeHeadMap(java.util.Map<Integer, String> headMap, AnalysisContext context) {
if (!headerRead) {
actualHeaders.addAll(headMap.values());
headerRead = true;
}
}
@Override
public void invoke(T t, AnalysisContext analysisContext) {
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 验证表头
if (!expectedHeaders.equals(actualHeaders)) {
throw new BusinessException("表头格式不正确,预期表头:" + expectedHeaders + ",实际表头:" + actualHeaders);
}
}
}
}

View File

@ -0,0 +1,90 @@
package com.eleadmin.common.core.utils;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
@Component
public class SmartMybatisUtil {
private static SqlSessionFactory sqlSessionFactory;
public SmartMybatisUtil(SqlSessionFactory sqlSessionFactory) {
SmartMybatisUtil.sqlSessionFactory = sqlSessionFactory;
}
/**
* 批量插入数据
*
* @param mapperInterface MyBatis Mapper接口类
* @param dataList 要插入的数据列表
* @param batchSize 每批次插入的数据量
* @param <T> 数据类型
* @param <M> Mapper接口类型
*/
public static <T, M extends BaseMapper<T>> void batchInsert(Class<M> mapperInterface, List<T> dataList, int batchSize) {
if (CollectionUtils.isEmpty(dataList)) {
return;
}
try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false)) {
M mapper = sqlSession.getMapper(mapperInterface);
for (int i = 0; i < dataList.size(); i++) {
mapper.insert(dataList.get(i));
if (i % batchSize == 0) {
sqlSession.commit();
sqlSession.clearCache();
}
}
sqlSession.commit();
} catch (Exception e) {
throw new RuntimeException("Batch insert failed", e);
}
}
/**
* 执行批量更新操作
* 该方法用于高效地批量更新数据列表中的实体通过指定的映射接口和批次大小
* 主要目的是减少数据库的访问次数提高更新效率
*
* @param mapperInterface 映射接口的Class类型用于获取映射器
* @param dataList 待更新的数据列表
* @param batchSize 每次批量更新的数量
* @param <T> 数据实体的类型
* @param <M> 映射接口的类型必须继承自BaseMapper
*/
public static <T, M extends BaseMapper<T>> void batchUpdate(Class<M> mapperInterface, List<T> dataList, int batchSize) {
// 检查数据列表是否为空如果为空则直接返回
if (CollectionUtils.isEmpty(dataList)) {
return;
}
try {
// 使用try-with-resources确保SqlSession在操作完成后会被正确关闭
// 打开一个批处理类型的SqlSession不自动提交事务
try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false)) {
// 获取映射接口对应的映射器实例
M mapper = sqlSession.getMapper(mapperInterface);
// 遍历数据列表执行批量更新操作
for (int i = 0; i < dataList.size(); i++) {
// 调用映射器的按ID更新方法
mapper.updateById(dataList.get(i));
// 每处理batchSize数量的数据后提交一次事务并清空缓存
if (i % batchSize == 0) {
sqlSession.commit();
sqlSession.clearCache();
}
}
// 最后确保所有更新操作都已提交
sqlSession.commit();
}
} catch (Exception e) {
// 如果发生异常抛出运行时异常包含异常信息
throw new RuntimeException("Batch update failed", e);
}
}
}

View File

@ -0,0 +1,61 @@
package com.eleadmin.common.core.utils;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.eleadmin.common.core.web.ApiResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
/**
* 返回工具栏
*
* @Author 1024创新实验室-主任:卓大
* @Date 2023/11/25 18:51:32
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>Since 2012
*/
@Slf4j
public class SmartResponseUtil {
public static void write(HttpServletResponse response, ApiResult<?> ApiResult) {
// 重置response
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
try {
response.getWriter().write(JSON.toJSONString(ApiResult));
response.flushBuffer();
} catch (IOException ex) {
log.error(ex.getMessage(), ex);
throw new RuntimeException(ex);
}
}
public static void setDownloadFileHeader(HttpServletResponse response, String fileName) {
setDownloadFileHeader(response, fileName, null);
}
public static void setDownloadFileHeader(HttpServletResponse response, String fileName, Long fileSize) {
response.setCharacterEncoding("utf-8");
if (fileSize != null) {
response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileSize));
}
if (StrUtil.isNotEmpty(fileName)) {
response.setHeader(HttpHeaders.CONTENT_TYPE, MediaTypeFactory.getMediaType(fileName).orElse(MediaType.APPLICATION_OCTET_STREAM) + ";charset=utf-8");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8).replaceAll("\\+", "%20"));
response.setHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_DISPOSITION);
}
}
}

View File

@ -0,0 +1,218 @@
package com.eleadmin.common.core.utils;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* @author 张小张
* @describe 压缩多个文件
* @date 2023/07/18 18:10
*/
public class ZipUtils {
public static void downloadAndZipFiles(HttpServletResponse response, List<String> filePaths, String zipFileName) {
try {
// 设置响应头告诉浏览器这是一个压缩文件用于下载
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=" + zipFileName);
// 创建ZipOutputStream对象
ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream());
Map<String, Integer> existingFileNames = new HashMap<>();
// 将文件逐个添加到压缩包中
for (String filePath : filePaths) {
File file = new File(filePath);
if (file.exists()) {
addToZip(zipOut, file, existingFileNames);
}
}
// 关闭ZipOutputStream
zipOut.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void addToZip(ZipOutputStream zipOut, File file, Map<String, Integer> existingFileNames) throws IOException {
if (file.isFile()) {
FileInputStream fis = new FileInputStream(file);
// 获取文件名并对文件名进行处理
String fileName = file.getName();
fileName = removeContentBetweenUnderscoreAndDot(fileName);
// 处理重名文件
if (existingFileNames.containsKey(fileName)) {
int count = existingFileNames.get(fileName);
count++;
fileName = addCountToFileName(fileName, count);
existingFileNames.put(fileName, count);
} else {
existingFileNames.put(fileName, 1);
}
// 添加到压缩包
zipOut.putNextEntry(new ZipEntry(fileName));
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) >= 0) {
zipOut.write(bytes, 0, length);
}
fis.close();
zipOut.closeEntry();
}
}
private static String removeContentBetweenUnderscoreAndDot(String fileName) {
// 查找第一个'_'的位置
int underscoreIndex = fileName.indexOf('_');
// 查找第一个'.'的位置
int dotIndex = fileName.indexOf('.');
// 如果找到了'_''.'并且'_''.'之前执行去除操作
if (underscoreIndex != -1 && dotIndex != -1 && underscoreIndex < dotIndex) {
// 获取'_''.'之间的内容
String contentToRemove = fileName.substring(underscoreIndex, dotIndex);
// 替换掉'_''.'之间的内容为空字符串
fileName = fileName.replace(contentToRemove, "");
}
return fileName;
}
private static String addCountToFileName(String fileName, int count) {
int dotIndex = fileName.lastIndexOf('.');
if (dotIndex != -1) {
String name = fileName.substring(0, dotIndex);
String extension = fileName.substring(dotIndex);
return name + "(" + count + ")" + extension;
} else {
return fileName + "(" + count + ")";
}
}
/**
* 文件夹压缩成ZIP
*
* @param zipFileName 生成压缩文件夹路径
* @param sourceFileName 要压缩的文件路径
* @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
* false:所有文件跑到压缩包根目录下(注意不保留目录结构可能会出现同名文件,会压缩失败)
* @throws RuntimeException 压缩失败会抛出运行时异常
*/
public static Boolean folderToZip(String zipFileName, String sourceFileName, boolean KeepDirStructure) {
Boolean result = true;
long start = System.currentTimeMillis();//开始
ZipOutputStream zos = null;
try {
FileOutputStream fileOutputStream = new FileOutputStream(zipFileName);
zos = new ZipOutputStream(fileOutputStream);
File sourceFile = new File(sourceFileName);
compress(sourceFile, zos, sourceFile.getName(), KeepDirStructure);
long end = System.currentTimeMillis();//结束
System.out.println("压缩完成,耗时:" + (end - start) + " 毫秒");
} catch (Exception e) {
result = false;
e.printStackTrace();
} finally {
if (zos != null) {
try {
zos.close();
} catch (IOException e) {
e.getStackTrace();
}
}
}
return result;
}
/**
* 递归压缩方法
*
* @param sourceFile 源文件
* @param zos zip输出流
* @param name 压缩后的名称
* @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
* false:所有文件跑到压缩包根目录下(注意不保留目录结构可能会出现同名文件,会压缩失败)
* @throws Exception
*/
public static void compress(File sourceFile, ZipOutputStream zos, String name,
boolean KeepDirStructure) throws Exception {
if (sourceFile.isFile()) {
// 向zip输出流中添加一个zip实体构造器中name为zip实体的文件的名字
zos.putNextEntry(new ZipEntry(name));
// copy文件到zip输出流中
int len;
byte[] buf = new byte[1024];
FileInputStream in = new FileInputStream(sourceFile);
while ((len = in.read(buf)) != -1) {
zos.write(buf, 0, len);
}
// Complete the entry
zos.closeEntry();
in.close();
} else {
File[] listFiles = sourceFile.listFiles();
if (listFiles == null || listFiles.length == 0) {
// 需要保留原来的文件结构时,需要对空文件夹进行处理
if (KeepDirStructure) {
// 空文件夹的处理
zos.putNextEntry(new ZipEntry(name + "/"));
// 没有文件不需要文件的copy
zos.closeEntry();
}
} else {
for (File file : listFiles) {
// 判断是否需要保留原来的文件结构
if (KeepDirStructure) {
// 注意file.getName()前面需要带上父文件夹的名字加一斜杠,
// 不然最后压缩包中就不能保留原来的文件结构,所有文件都跑到压缩包根目录下了
compress(file, zos, name + "/" + file.getName(), KeepDirStructure);
} else {
compress(file, zos, file.getName(), KeepDirStructure);
}
}
}
}
}
public static void copyFolder(File sourceFolder, File targetFolder) throws IOException {
if (sourceFolder.isDirectory()) {
if (!targetFolder.exists()) {
targetFolder.mkdirs();
}
for (File file : sourceFolder.listFiles()) {
if (file.isDirectory()) {
copyFolder(file, new File(targetFolder + File.separator + file.getName()));
} else {
Files.copy(file.toPath(), Paths.get(targetFolder + File.separator + file.getName()), StandardCopyOption.REPLACE_EXISTING);
}
}
}else {
if (!targetFolder.exists()) {
targetFolder.mkdirs();
}
Files.copy(sourceFolder.toPath(), Paths.get(targetFolder + File.separator + sourceFolder.getName()), StandardCopyOption.REPLACE_EXISTING);
}
}
}

View File

@ -0,0 +1,101 @@
package com.eleadmin.common.core.web;
import com.eleadmin.common.core.Constants;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
/**
* 返回结果
*
* @author EleAdmin
* @since 2017-06-10 10:10:50
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ApiResult<T> implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "状态码")
private Integer code;
@ApiModelProperty(value = "状态信息")
private String message;
@ApiModelProperty(value = "返回数据")
private T data;
@ApiModelProperty(value = "错误信息")
private String error;
public ApiResult() {
}
public ApiResult(Integer code) {
this(code, null);
}
public ApiResult(Integer code, String message) {
this(code, message, null);
}
public ApiResult(Integer code, String message, T data) {
this(code, message, data, null);
}
public ApiResult(Integer code, String message, T data, String error) {
setCode(code);
setMessage(message);
setData(data);
setError(error);
}
public static ApiResult<String> ok() {
return new ApiResult<>(Constants.RESULT_OK_CODE, Constants.RESULT_OK_MSG);
}
public static ApiResult<String> okMsg(String msg) {
return new ApiResult<>(Constants.RESULT_OK_CODE, msg);
}
public static ApiResult<String> fail() {
return new ApiResult<>(Constants.RESULT_ERROR_CODE, Constants.RESULT_ERROR_MSG);
}
public Integer getCode() {
return this.code;
}
public ApiResult<T> setCode(Integer code) {
this.code = code;
return this;
}
public String getMessage() {
return this.message;
}
public ApiResult<T> setMessage(String message) {
this.message = message;
return this;
}
public T getData() {
return this.data;
}
public ApiResult<T> setData(T data) {
this.data = data;
return this;
}
public String getError() {
return this.error;
}
public ApiResult<T> setError(String error) {
this.error = error;
return this;
}
}

View File

@ -0,0 +1,160 @@
package com.eleadmin.common.core.web;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.eleadmin.common.core.Constants;
import com.eleadmin.common.system.entity.User;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import java.util.List;
/**
* Controller基类
*
* @author EleAdmin
* @since 2017-06-10 10:10:19
*/
public class BaseController {
/**
* 获取当前登录的user
*
* @return User
*/
public User getLoginUser() {
try {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) {
Object object = authentication.getPrincipal();
if (object instanceof User) {
return (User) object;
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
return null;
}
/**
* 获取当前登录的userId
*
* @return userId
*/
public Integer getLoginUserId() {
User loginUser = getLoginUser();
return loginUser == null ? null : loginUser.getUserId();
}
/**
* 返回成功
*
* @return ApiResult
*/
public ApiResult<?> success() {
return new ApiResult<>(Constants.RESULT_OK_CODE, Constants.RESULT_OK_MSG);
}
/**
* 返回成功
*
* @param message 状态信息
* @return ApiResult
*/
public ApiResult<?> success(String message) {
return success().setMessage(message);
}
/**
* 返回成功
*
* @param data 返回数据
* @return ApiResult
*/
public <T> ApiResult<T> success(T data) {
return new ApiResult<>(Constants.RESULT_OK_CODE, Constants.RESULT_OK_MSG, data);
}
/**
* 返回成功
*
* @param message 状态信息
* @return ApiResult
*/
public <T> ApiResult<T> success(String message, T data) {
return success(data).setMessage(message);
}
/**
* 返回分页查询数据
*
* @param list 当前页数据
* @param count 总数量
* @return ApiResult
*/
public <T> ApiResult<PageResult<T>> success(List<T> list, Long count) {
return success(new PageResult<>(list, count));
}
/**
* 返回分页查询数据
*
* @param iPage IPage
* @return ApiResult
*/
public <T> ApiResult<PageResult<T>> success(IPage<T> iPage) {
return success(iPage.getRecords(), iPage.getTotal());
}
/**
* 返回失败
*
* @return ApiResult
*/
public ApiResult<?> fail() {
return new ApiResult<>(Constants.RESULT_ERROR_CODE, Constants.RESULT_ERROR_MSG);
}
/**
* 返回失败
*
* @param message 状态信息
* @return ApiResult
*/
public ApiResult<?> fail(String message) {
return fail().setMessage(message);
}
/**
* 返回失败
*
* @param data 返回数据
* @return ApiResult
*/
public <T> ApiResult<T> fail(T data) {
return fail(Constants.RESULT_ERROR_MSG, data);
}
/**
* 返回失败
*
* @param message 状态信息
* @param data 返回数据
* @return ApiResult
*/
public <T> ApiResult<T> fail(String message, T data) {
return new ApiResult<>(Constants.RESULT_ERROR_CODE, message, data);
}
/**
* 请求参数的空字符串转为null
*/
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
}
}

View File

@ -0,0 +1,59 @@
package com.eleadmin.common.core.web;
import com.baomidou.mybatisplus.annotation.TableField;
import com.eleadmin.common.core.annotation.QueryField;
import com.eleadmin.common.core.annotation.QueryType;
import com.eleadmin.common.core.utils.CommonUtil;
import lombok.Data;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.List;
/**
* 查询参数基本字段
*
* @author EleAdmin
* @since 2021-08-26 22:14:43
*/
@Data
public class BaseParam implements Serializable {
private static final long serialVersionUID = 1L;
@TableField(exist = false)
@ApiModelProperty("分页查询页码")
private Long page;
@TableField(exist = false)
@ApiModelProperty("分页查询每页数量")
private Long limit;
@TableField(exist = false)
@ApiModelProperty(value = "排序字段", notes = "排序字段或sql, 如果是sql则order字段无用, 如: `id asc, name desc`")
private String sort;
@TableField(exist = false)
@ApiModelProperty(value = "排序方式", notes = "sort是字段名称时对应的排序方式, asc升序, desc降序")
private String order;
@QueryField(value = "create_time", type = QueryType.GE)
@TableField(exist = false)
@ApiModelProperty("创建时间起始值")
private String createTimeStart;
@QueryField(value = "create_time", type = QueryType.LE)
@TableField(exist = false)
@ApiModelProperty("创建时间结束值")
private String createTimeEnd;
/**
* 获取集合中的第一条数据
*
* @param records 集合
* @return 第一条数据
*/
public <T> T getOne(List<T> records) {
return CommonUtil.listGetOne(records);
}
}

View File

@ -0,0 +1,57 @@
package com.eleadmin.common.core.web;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.service.IService;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 批量修改通用参数
*
* @author EleAdmin
* @since 2020-03-13 00:11:06
*/
@Data
public class BatchParam<T> implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "需要修改的数据id集合")
private List<Serializable> ids;
@ApiModelProperty(value = "需要修改的字段和值")
private T data;
/**
* 通用批量修改方法
*
* @param service IService
* @param idField id字段名称
* @return boolean
*/
public boolean update(IService<T> service, String idField) {
if (this.data == null) {
return false;
}
return service.update(this.data, new UpdateWrapper<T>().in(idField, this.ids));
}
/**
* 通用批量修改方法
*
* @param service IService
* @param idField id字段名称
* @return boolean
*/
public boolean update(IService<T> service, SFunction<T, ?> idField) {
if (this.data == null) {
return false;
}
return service.update(this.data, new LambdaUpdateWrapper<T>().in(idField, this.ids));
}
}

View File

@ -0,0 +1,96 @@
package com.eleadmin.common.core.web;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.service.IService;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 检查是否存在通用参数
*
* @author EleAdmin
* @since 2021-09-07 22:24:39
*/
@Data
public class ExistenceParam<T> implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "检查的字段")
private String field;
@ApiModelProperty(value = "字段的值")
private String value;
@ApiModelProperty(value = "修改时的主键")
private Integer id;
/**
* 检查是否存在
*
* @param service IService
* @param idField 修改时的主键字段
* @return boolean
*/
public boolean isExistence(IService<T> service, String idField) {
return isExistence(service, idField, true);
}
/**
* 检查是否存在
*
* @param service IService
* @param idField 修改时的主键字段
* @param isToUnderlineCase 是否需要把field转为下划线格式
* @return boolean
*/
public boolean isExistence(IService<T> service, String idField, boolean isToUnderlineCase) {
if (StrUtil.hasBlank(this.field, this.value)) {
return false;
}
String fieldName = isToUnderlineCase ? StrUtil.toUnderlineCase(field) : field;
QueryWrapper<T> wrapper = new QueryWrapper<>();
wrapper.eq(fieldName, value);
if (id != null) {
wrapper.ne(idField, id);
}
return service.count(wrapper) > 0;
}
/**
* 检查是否存在
*
* @param service IService
* @param idField 修改时的主键字段
* @return boolean
*/
public boolean isExistence(IService<T> service, SFunction<T, ?> idField) {
return isExistence(service, idField, true);
}
/**
* 检查是否存在
*
* @param service IService
* @param idField 修改时的主键字段
* @param isToUnderlineCase 是否需要把field转为下划线格式
* @return boolean
*/
public boolean isExistence(IService<T> service, SFunction<T, ?> idField, boolean isToUnderlineCase) {
if (StrUtil.hasBlank(this.field, this.value)) {
return false;
}
String fieldName = isToUnderlineCase ? StrUtil.toUnderlineCase(field) : field;
LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
wrapper.apply(fieldName + " = {0}", value);
if (id != null) {
wrapper.ne(idField, id);
}
return service.count(wrapper) > 0;
}
}

View File

@ -0,0 +1,343 @@
package com.eleadmin.common.core.web;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eleadmin.common.core.Constants;
import com.eleadmin.common.core.annotation.QueryField;
import com.eleadmin.common.core.annotation.QueryType;
import com.eleadmin.common.core.utils.CommonUtil;
import java.lang.reflect.Field;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 分页排序搜索参数封装
*
* @author EleAdmin
* @since 2019-04-26 10:34:35
*/
public class PageParam<T, U extends BaseParam> extends Page<T> {
private static final long serialVersionUID = 1L;
/**
* 租户id字段名称
*/
private static final String TENANT_ID_FIELD = "tenantId";
/**
* 查询条件
*/
private final U where;
/**
* 是否把字段名称驼峰转下划线
*/
private final boolean isToUnderlineCase;
public PageParam() {
this(null);
}
public PageParam(U where) {
this(where, true);
}
public PageParam(U where, boolean isToUnderlineCase) {
super();
this.where = where;
this.isToUnderlineCase = isToUnderlineCase;
if (where != null) {
// 获取分页页码
if (where.getPage() != null) {
setCurrent(where.getPage());
}
// 获取分页每页数量
if (where.getLimit() != null) {
setSize(where.getLimit());
}
// 获取排序方式
if (where.getSort() != null) {
if (sortIsSQL(where.getSort())) {
setOrders(parseOrderSQL(where.getSort()));
} else {
List<OrderItem> orderItems = new ArrayList<>();
String column = this.isToUnderlineCase ? StrUtil.toUnderlineCase(where.getSort()) : where.getSort();
boolean asc = !Constants.ORDER_DESC_VALUE.equals(where.getOrder());
orderItems.add(new OrderItem().setAsc(asc).setColumn(column));
setOrders(orderItems);
}
}
}
}
/**
* 排序字段是否是sql
*/
private boolean sortIsSQL(String sort) {
return sort != null && (sort.contains(",") || sort.trim().contains(" "));
}
/**
* 解析排序sql
*/
private List<OrderItem> parseOrderSQL(String orderSQL) {
List<OrderItem> orders = new ArrayList<>();
if (StrUtil.isNotBlank(orderSQL)) {
for (String item : orderSQL.split(",")) {
String[] temp = item.trim().split(" ");
if (!temp[0].isEmpty()) {
String column = this.isToUnderlineCase ? StrUtil.toUnderlineCase(temp[0]) : temp[0];
boolean asc = temp.length == 1 || !temp[temp.length - 1].equals(Constants.ORDER_DESC_VALUE);
orders.add(new OrderItem().setAsc(asc).setColumn(column));
}
}
}
return orders;
}
/**
* 设置默认排序方式
*
* @param orderItems 排序方式
* @return PageParam
*/
public PageParam<T, U> setDefaultOrder(List<OrderItem> orderItems) {
if (orders() == null || orders().size() == 0) {
setOrders(orderItems);
}
return this;
}
/**
* 设置默认排序方式
*
* @param orderSQL 排序方式
* @return PageParam
*/
public PageParam<T, U> setDefaultOrder(String orderSQL) {
setDefaultOrder(parseOrderSQL(orderSQL));
return this;
}
/**
* 获取查询条件
*
* @param excludes 不包含的字段
* @return QueryWrapper
*/
public QueryWrapper<T> getWrapper(String... excludes) {
return buildWrapper(null, Arrays.asList(excludes));
}
/**
* 获取查询条件
*
* @param columns 只包含的字段
* @return QueryWrapper
*/
public QueryWrapper<T> getWrapperWith(String... columns) {
return buildWrapper(Arrays.asList(columns), null);
}
/**
* 构建QueryWrapper
*
* @param columns 包含的字段
* @param excludes 排除的字段
* @return QueryWrapper
*/
private QueryWrapper<T> buildWrapper(List<String> columns, List<String> excludes) {
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
Map<String, Object> map = BeanUtil.beanToMap(where, false, true);
for (String fieldName : map.keySet()) {
Object fieldValue = map.get(fieldName);
Field field = ReflectUtil.getField(where.getClass(), fieldName);
// 过滤不包含的字段
if (columns != null && !columns.contains(fieldName)) {
continue;
}
// 过滤排除的字段
if (excludes != null && excludes.contains(fieldName)) {
continue;
}
// 过滤逻辑删除字段
if (field.getAnnotation(TableLogic.class) != null) {
continue;
}
// 过滤租户id字段
if (fieldName.equals(TENANT_ID_FIELD)) {
continue;
}
// 获取注解指定的查询字段及查询方式
QueryType queryType = QueryType.LIKE;
QueryField queryField = field.getAnnotation(QueryField.class);
if (queryField != null) {
if (StrUtil.isNotEmpty(queryField.value())) {
fieldName = queryField.value();
}
if (queryField.type() != null) {
queryType = queryField.type();
}
} else {
// 过滤非本表的字段
TableField tableField = field.getAnnotation(TableField.class);
if (tableField != null && !tableField.exist()) {
continue;
}
}
// 字段名驼峰转下划线
if (this.isToUnderlineCase) {
fieldName = StrUtil.toUnderlineCase(fieldName);
}
//
switch (queryType) {
case EQ:
queryWrapper.eq(fieldName, fieldValue);
break;
case NE:
queryWrapper.ne(fieldName, fieldValue);
break;
case GT:
queryWrapper.gt(fieldName, fieldValue);
break;
case GE:
queryWrapper.ge(fieldName, fieldValue);
break;
case LT:
queryWrapper.lt(fieldName, fieldValue);
break;
case LE:
queryWrapper.le(fieldName, fieldValue);
break;
case LIKE:
queryWrapper.like(fieldName, fieldValue);
break;
case NOT_LIKE:
queryWrapper.notLike(fieldName, fieldValue);
break;
case LIKE_LEFT:
queryWrapper.likeLeft(fieldName, fieldValue);
break;
case LIKE_RIGHT:
queryWrapper.likeRight(fieldName, fieldValue);
break;
case IS_NULL:
queryWrapper.isNull(fieldName);
break;
case IS_NOT_NULL:
queryWrapper.isNotNull(fieldName);
break;
case IN:
queryWrapper.in(fieldName, fieldValue);
break;
case NOT_IN:
queryWrapper.notIn(fieldName, fieldValue);
break;
case IN_STR:
if (fieldValue instanceof String) {
queryWrapper.in(fieldName, Arrays.asList(((String) fieldValue).split(",")));
}
break;
case NOT_IN_STR:
if (fieldValue instanceof String) {
queryWrapper.notIn(fieldName, Arrays.asList(((String) fieldValue).split(",")));
}
break;
}
}
return queryWrapper;
}
/**
* 获取包含排序的查询条件
*
* @return 包含排序的QueryWrapper
*/
public QueryWrapper<T> getOrderWrapper() {
return getOrderWrapper(getWrapper());
}
/**
* 获取包含排序的查询条件
*
* @param queryWrapper 不含排序的QueryWrapper
* @return 包含排序的QueryWrapper
*/
public QueryWrapper<T> getOrderWrapper(QueryWrapper<T> queryWrapper) {
if (queryWrapper == null) {
queryWrapper = new QueryWrapper<>();
}
for (OrderItem orderItem : orders()) {
if (orderItem.isAsc()) {
queryWrapper.orderByAsc(orderItem.getColumn());
} else {
queryWrapper.orderByDesc(orderItem.getColumn());
}
}
return queryWrapper;
}
/**
* 获取集合中的第一条数据
*
* @param records 集合
* @return 第一条数据
*/
public T getOne(List<T> records) {
return CommonUtil.listGetOne(records);
}
/**
* 代码排序集合
*
* @param records 集合
* @return 排序后的集合
*/
public List<T> sortRecords(List<T> records) {
List<OrderItem> orderItems = orders();
if (records == null || records.size() < 2 || orderItems == null || orderItems.size() == 0) {
return records;
}
Comparator<T> comparator = null;
for (OrderItem item : orderItems) {
if (item.getColumn() == null) {
continue;
}
String field = this.isToUnderlineCase ? StrUtil.toCamelCase(item.getColumn()) : item.getColumn();
Function keyExtractor = t -> ReflectUtil.getFieldValue(t, field);
if (comparator == null) {
if (item.isAsc()) {
comparator = Comparator.comparing(keyExtractor);
} else {
comparator = Comparator.comparing(keyExtractor, Comparator.reverseOrder());
}
} else {
if (item.isAsc()) {
comparator.thenComparing(keyExtractor);
} else {
comparator.thenComparing(keyExtractor, Comparator.reverseOrder());
}
}
}
if (comparator != null) {
return records.stream().sorted(comparator).collect(Collectors.toList());
}
return records;
}
}

View File

@ -0,0 +1,51 @@
package com.eleadmin.common.core.web;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.List;
/**
* 分页查询返回结果
*
* @author EleAdmin
* @since 2017-06-10 10:10:02
*/
public class PageResult<T> implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "当前页数据")
private List<T> list;
@ApiModelProperty(value = "总数量")
private Long count;
public PageResult() {
}
public PageResult(List<T> list) {
this(list, null);
}
public PageResult(List<T> list, Long count) {
setList(list);
setCount(count);
}
public List<T> getList() {
return this.list;
}
public void setList(List<T> list) {
this.list = list;
}
public Long getCount() {
return this.count;
}
public void setCount(Long count) {
this.count = count;
}
}

View File

@ -0,0 +1,158 @@
package com.eleadmin.common.distributiondeviceinfo.controller;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import com.eleadmin.common.core.web.ApiResult;
import com.eleadmin.common.core.web.BaseController;
import com.eleadmin.common.distributiondeviceinfo.domain.form.*;
import com.eleadmin.common.distributiondeviceinfo.service.DistributionDeviceInfoService;
import com.eleadmin.common.powerdebug.domain.entity.PowerDebugEntity;
import com.eleadmin.common.core.utils.SmartResponseUtil;
import com.eleadmin.common.system.param.IdParam;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
/**
* 配电设备新投异动图模维护信息表 Controller
*
* @Author 王益亭
* @Date 2025-02-28 14:39:52
* @Copyright gxrd
*/
@RestController
@Tag(name = "配电设备新投异动图模维护信息表")
public class DistributionDeviceInfoController extends BaseController {
@Resource
private DistributionDeviceInfoService distributionDeviceInfoService;
@Operation(summary = "分页查询 @author 王益亭")
@PostMapping("/api/distributionDeviceInfo/queryPage")
// @SaCheckPermission("distributionDeviceInfo:query")
@PreAuthorize("hasAuthority('distributionDeviceInfo:query')")
public ApiResult queryPage(@RequestBody @Valid DistributionDeviceInfoQueryForm queryForm) {
List<Integer> collect = getLoginUser().getRoles().stream().map(r -> r.getRoleId()).collect(Collectors.toList());
if (!collect.contains(1)) {
queryForm.setCreateUser(getLoginUser().getUserId());
}
return success(distributionDeviceInfoService.querySimplePage(queryForm));
}
@Operation(summary = "查询关联信息 @author 王益亭")
@PostMapping("/api/distributionDeviceInfo/link")
// // @SaCheckPermission("distributionDeviceInfo:query")
@PreAuthorize("hasAuthority('distributionDeviceInfo:query')")
public ApiResult<PowerDebugEntity> queryLink(@RequestBody @Valid DistributionDeviceInfoLinkQueryForm queryForm) {
return success(distributionDeviceInfoService.queryLink(queryForm));
}
@Operation(summary = "根据ID查询 @author 王益亭")
@PostMapping("/api/distributionDeviceInfo/{id}")
// // @SaCheckPermission("distributionDeviceInfo:query")
@PreAuthorize("hasAuthority('distributionDeviceInfo:query')")
public ApiResult getById(@PathVariable Integer id) {
return success(distributionDeviceInfoService.getById(id));
}
@Operation(summary = "导入Excel @author 王益亭")
@PostMapping("/api/distributionDeviceInfo/importExcel")
// // @SaCheckPermission("distributionDeviceInfo:import")
@PreAuthorize("hasAuthority('distributionDeviceInfo:import')")
public ApiResult importExcel(@RequestParam("file") MultipartFile file) {
List<Integer> collect = getLoginUser().getRoles().stream().map(r -> r.getRoleId()).collect(Collectors.toList());
Integer commitStatus = null;
if (collect.contains(1)) {
commitStatus = 1;
}
distributionDeviceInfoService.importFromExcel(file,getLoginUserId(),commitStatus);
return success();
}
@Operation(summary = "查询excel数据 ")
@GetMapping("/api/distributionDeviceInfo/getExcelInfo")
// // @SaCheckPermission("distributionDeviceInfo:import")
@PreAuthorize("hasAuthority('distributionDeviceInfo:import')")
public ApiResult getExcel( Integer id ) throws IOException {
return success(distributionDeviceInfoService.getExcel(id));
}
@Operation(summary = "模板 @author 王益亭")
@GetMapping("/api/distributionDeviceInfo/model")
// @SaCheckPermission("distributionDeviceInfo:import")
@PreAuthorize("hasAuthority('distributionDeviceInfo:import')")
public void model(HttpServletResponse response) throws IOException {
// 设置下载消息头
SmartResponseUtil.setDownloadFileHeader(response, "新投异动模板.xls", null);
cn.hutool.core.io.resource.Resource resource = ResourceUtil.getResourceObj("classpath:/model/model.xls");
System.out.println(resource.getUrl());
IoUtil.copy(resource.getStream(),response.getOutputStream());
}
@Operation(summary = "添加 @author 王益亭")
@PostMapping("/api/distributionDeviceInfo/add")
// @SaCheckPermission("distributionDeviceInfo:add")
public ApiResult<String> add(@RequestBody DistributionDeviceInfoLinkAddForm addForm) {
List<Integer> collect = getLoginUser().getRoles().stream().map(r -> r.getRoleId()).collect(Collectors.toList());
if (collect.contains(1)) {
addForm.getLeft().setCommitStatus(1);
addForm.getLeft().setCommitTime(LocalDateTime.now());
}
addForm.getLeft().setCreateUser(getLoginUserId());
return distributionDeviceInfoService.add(addForm);
}
@Operation(summary = "提交")
@PostMapping("/api/distributionDeviceInfo/commit")
// @SaCheckPermission("distributionDeviceInfo:add")
public ApiResult commit(@RequestBody @Valid IdParam idParam) {
distributionDeviceInfoService.commit(idParam);
return success();
}
@Operation(summary = "撤销提交")
@PostMapping("/api/distributionDeviceInfo/repealCommit")
// @SaCheckPermission("distributionDeviceInfo:add")
public ApiResult repealCommit(@RequestBody @Valid IdParam idParam) {
distributionDeviceInfoService.repealCommit(idParam);
return success();
}
@Operation(summary = "更新 @author 王益亭")
@PostMapping("/api/distributionDeviceInfo/update")
// @SaCheckPermission("distributionDeviceInfo:update")
public ApiResult<String> update(@RequestBody DistributionDeviceInfoLinkUpdateForm updateForm) {
List<Integer> collect = getLoginUser().getRoles().stream().map(r -> r.getRoleId()).collect(Collectors.toList());
Integer createUser = null;
if (!collect.contains(1)) {
createUser = getLoginUserId();
}
return distributionDeviceInfoService.update(updateForm,createUser);
}
@Operation(summary = "批量删除 @author 王益亭")
@PostMapping("/api/distributionDeviceInfo/batchDelete")
// @SaCheckPermission("distributionDeviceInfo:delete")
public ApiResult<?> batchDelete(@RequestBody List<Integer> idList) {
return distributionDeviceInfoService.batchDelete(idList);
}
@Operation(summary = "单个删除 @author 王益亭")
@GetMapping("/api/distributionDeviceInfo/delete/{id}")
// @SaCheckPermission("distributionDeviceInfo:delete")
public ApiResult<?> batchDelete(@PathVariable Integer id) {
return distributionDeviceInfoService.delete(id);
}
}

View File

@ -0,0 +1,37 @@
package com.eleadmin.common.distributiondeviceinfo.dao;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eleadmin.common.core.web.PageParam;
import com.eleadmin.common.distributiondeviceinfo.domain.entity.DistributionDeviceInfoEntity;
import com.eleadmin.common.distributiondeviceinfo.domain.form.DistributionDeviceInfoQueryForm;
import com.eleadmin.common.distributiondeviceinfo.domain.vo.DistributionDeviceInfoVO;
import com.eleadmin.common.distributiondeviceinfo.domain.vo.DistributionDeviceSimpleVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;
/**
* 配电设备新投异动图模维护信息表 Dao
*
* @Author 王益亭
* @Date 2025-02-28 14:39:52
* @Copyright gxrd
*/
@Mapper
@Component
public interface DistributionDeviceInfoDao extends BaseMapper<DistributionDeviceInfoEntity> {
/**
* 分页 查询
*
* @param page
* @param queryForm
* @return
*/
List<DistributionDeviceInfoVO> queryPage(Page page, @Param("queryForm") DistributionDeviceInfoQueryForm queryForm);
List<DistributionDeviceSimpleVO> querySimplePage(Page page,@Param("queryForm") DistributionDeviceInfoQueryForm queryForm);
}

View File

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.eleadmin.common.distributiondeviceinfo.dao.DistributionDeviceInfoDao">
<!-- 查询结果列 -->
<sql id="base_columns">
t_distribution_device_info.id,
t_distribution_device_info.scheduled_work_time,
t_distribution_device_info.plan_work_feeder,
t_distribution_device_info.plan_work_time,
t_distribution_device_info.line_name,
t_distribution_device_info.oms_number,
t_distribution_device_info.main_project_name,
t_distribution_device_info.main_project_code,
t_distribution_device_info.is_main_project,
t_distribution_device_info.operating_unit_contact,
t_distribution_device_info.customer_project_name,
t_distribution_device_info.customer_project_code,
t_distribution_device_info.involves_physical_id,
t_distribution_device_info.operating_unit_scanner,
t_distribution_device_info.new_equipment_maintenance,
t_distribution_device_info.contact_person,
t_distribution_device_info.special_equipment_cable_asset,
t_distribution_device_info.special_equipment_tap_switch_asset,
t_distribution_device_info.special_equipment_user_code,
t_distribution_device_info.major_customer_contact,
t_distribution_device_info.attachment,
t_distribution_device_info.whether_debug,
t_distribution_device_info.finish_status,
t_distribution_device_info.commit_status,
t_distribution_device_info.commit_time,
t_distribution_device_info.create_user,
t_distribution_device_info.create_time,
sys_file_record.name as attachment_name
</sql>
<resultMap id="page"
type="com.eleadmin.common.distributiondeviceinfo.domain.vo.DistributionDeviceInfoVO">
<id column="id" property="id"/>
<result column="scheduled_work_time" property="scheduledWorkTime"/>
<result column="line_name" property="lineName"/>
<result column="plan_work_feeder" property="planWorkFeeder"/>
<result column="plan_work_time" property="planWorkTime"/>
<result column="oms_number" property="omsNumber"/>
<result column="main_project_name" property="mainProjectName"/>
<result column="main_project_code" property="mainProjectCode"/>
<result column="is_main_project" property="isMainProject"/>
<result column="operating_unit_contact" property="operatingUnitContact"/>
<result column="customer_project_name" property="customerProjectName"/>
<result column="customer_project_code" property="customerProjectCode"/>
<result column="involves_physical_id" property="involvesPhysicalId"/>
<result column="operating_unit_scanner" property="operatingUnitScanner"/>
<result column="new_equipment_maintenance" property="newEquipmentMaintenance" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
<result column="contact_person" property="contactPerson"/>
<result column="special_equipment_cable_asset" property="specialEquipmentCableAsset"/>
<result column="special_equipment_tap_switch_asset" property="specialEquipmentTapSwitchAsset"/>
<result column="special_equipment_user_code" property="specialEquipmentUserCode"/>
<result column="major_customer_contact" property="majorCustomerContact"/>
<result column="attachment" property="attachment"/>
<result column="whether_debug" property="whetherDebug"/>
<result column="finish_status" property="finishStatus"/>
<result column="commit_status" property="commitStatus"/>
<result column="commit_time" property="commitTime"/>
<result column="create_user" property="createUser"/>
<result column="attachment_name" property="attachmentName"/>
</resultMap>
<!-- 分页查询 -->
<select id="queryPage" resultMap="page">
SELECT
<include refid="base_columns"/>
FROM t_distribution_device_info left join sys_file_record on sys_file_record.path = attachment
<where>
<if test="queryForm != null">
<if test="queryForm.id != null">
and t_distribution_device_info.id = #{queryForm.id}
</if>
<if test="queryForm.outageId != null">
and (t_distribution_device_info.outage_id = #{queryForm.outageId} or t_distribution_device_info.line_name = #{queryForm.lineName})
</if>
<if test="queryForm.planWorkTime != null">
and t_distribution_device_info.plan_work_time = #{queryForm.planWorkTime}
</if>
<if test="queryForm.lineName != null">
and t_distribution_device_info.line_name like concat('%',#{queryForm.lineName},'%')
</if>
</if>
</where>
</select>
<select id="querySimplePage"
resultType="com.eleadmin.common.distributiondeviceinfo.domain.vo.DistributionDeviceSimpleVO">
SELECT
<include refid="base_columns"/>
FROM t_distribution_device_info left join sys_file_record on sys_file_record.path = attachment
<where>
<if test="queryForm != null">
<if test="queryForm.id != null">
and t_distribution_device_info.id = #{queryForm.id}
</if>
<if test="queryForm.createUser != null">
and t_distribution_device_info.create_user = #{queryForm.createUser}
</if>
<if test="queryForm.planWorkTime != null">
and t_distribution_device_info.plan_work_time = #{queryForm.planWorkTime}
</if>
<if test="queryForm.lineName != null">
and t_distribution_device_info.line_name like concat('%',#{queryForm.lineName},'%')
</if>
</if>
</where>
</select>
</mapper>

View File

@ -0,0 +1,169 @@
package com.eleadmin.common.distributiondeviceinfo.domain.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 java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
/**
* 配电设备新投异动图模维护信息表 实体类
*
* @Author 王益亭
* @Date 2025-02-28 14:39:52
* @Copyright gxrd
*/
@Data
@TableName(value = "t_distribution_device_info", autoResultMap = true)
public class DistributionDeviceInfoEntity {
/**
* 记录ID
*/
@TableId(type = IdType.AUTO)
private Integer id;
/**
* 计划工作送电时间
*/
private LocalDateTime scheduledWorkTime;
/**
* 计划工作大馈线
*/
private String planWorkFeeder;
/**
* 计划工作时间
*/
private LocalDate planWorkTime;
/**
* 图模涉及大馈线名称
*/
private String lineName;
/**
* OMS新投异动编号
*/
private String omsNumber;
/**
* 主业工程名称
*/
private String mainProjectName;
/**
* 主业工程编号
*/
private String mainProjectCode;
/**
* 是否已推工程
*/
private Integer isMainProject;
/**
* 运行单位推工程人
*/
private String operatingUnitContact;
/**
* 客户工程名称
*/
private String customerProjectName;
/**
* 客户工程编号
*/
private String customerProjectCode;
/**
* 是否涉及主业实物ID扫码
*/
private Integer involvesPhysicalId;
/**
* 运行单位扫码人
*/
private String operatingUnitScanner;
/**
* 新增设备运行维护班组
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private List<NewDevice> newEquipmentMaintenance;
/**
* 联系人及电话
*/
private String contactPerson;
/**
* 专用设备进线电缆资产属性
*/
private String specialEquipmentCableAsset;
/**
* 专用设备T接点开关刀闸资产属性
*/
private String specialEquipmentTapSwitchAsset;
/**
* 专用设备用户编号
*/
private String specialEquipmentUserCode;
/**
* 大客户经理及联系方式
*/
private String majorCustomerContact;
/**
* 附件
*/
private String attachment;
/**
* 是否涉及调试0否1是
*/
private Integer whetherDebug;
/**
* 是否完成状态0否1是
*/
private Integer finishStatus;
/**
* 是否提交0否1是
*/
private Integer commitStatus;
/**
* 提交时间
*/
private LocalDateTime commitTime;
/**
* 创建人
*/
private Integer createUser;
/**
* 创建时间
*/
private LocalDateTime createTime;
private Integer outageId;
}

View File

@ -0,0 +1,14 @@
package com.eleadmin.common.distributiondeviceinfo.domain.entity;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
@Data
public class NewDevice {
@ExcelProperty("新设备名称")
private String deviceName;
@ExcelProperty("对应维护班组")
private String maintenanceTeam;
}

View File

@ -0,0 +1,96 @@
package com.eleadmin.common.distributiondeviceinfo.domain.form;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import lombok.Data;
import com.eleadmin.common.distributiondeviceinfo.domain.entity.NewDevice;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 配电设备新投异动图模维护信息表 新建表单
*
* @Author 王益亭
* @Date 2025-02-28 14:39:52
* @Copyright gxrd
*/
@Data
public class DistributionDeviceInfoAddForm {
@Schema(description = "计划工作(送电)时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime scheduledWorkTime;
@Schema(description = "计划工作大馈线")
private String planWorkFeeder;
@Schema(description = "计划工作时间")
@JsonFormat(pattern = "yyyy-MM-dd")
@NotNull(message = "计划工作时间不能为空")
private LocalDate planWorkTime;
@Schema(description = "图模涉及大馈线名称")
@NotBlank(message = "图模涉及大馈线名称不能为空")
private String lineName;
@Schema(description = "OMS新投异动编号")
private String omsNumber;
@Schema(description = "主业工程名称")
private String mainProjectName;
@Schema(description = "主业工程编号")
private String mainProjectCode;
@Schema(description = "是否已推工程")
private Integer isMainProject;
@Schema(description = "运行单位推工程人")
private String operatingUnitContact;
@Schema(description = "客户工程名称")
private String customerProjectName;
@Schema(description = "客户工程编号")
private String customerProjectCode;
@Schema(description = "是否涉及主业实物ID扫码")
private Integer involvesPhysicalId;
@Schema(description = "运行单位扫码人")
private String operatingUnitScanner;
@Schema(description = "新增设备运行维护班组")
private List<NewDevice> newEquipmentMaintenance;
@Schema(description = "联系人及电话")
private String contactPerson;
@Schema(description = "专用设备进线电缆资产属性")
private String specialEquipmentCableAsset;
@Schema(description = "专用设备T接点开关、刀闸资产属性")
private String specialEquipmentTapSwitchAsset;
@Schema(description = "专用设备用户编号")
private String specialEquipmentUserCode;
@Schema(description = "大客户经理及联系方式")
private String majorCustomerContact;
@Schema(description = "附件")
private String attachment;
@Schema(description = "提交状态")
private Integer commitStatus;
@Schema(description = "提交时间")
private LocalDateTime commitTime;
@Schema(description = "创建用户")
private Integer createUser;
}

View File

@ -0,0 +1,23 @@
package com.eleadmin.common.distributiondeviceinfo.domain.form;
import lombok.Data;
import com.eleadmin.common .powerdebug.domain.entity.PowerDebugEntity;
import javax.validation.Valid;
/**
* 配电设备新投异动图模维护信息表 关联新建表单
*
* @Author 王益亭
* @Date 2025-02-28 14:39:52
* @Copyright gxrd
*/
@Data
public class DistributionDeviceInfoLinkAddForm {
@Valid
private DistributionDeviceInfoAddForm left;
private PowerDebugEntity right;
}

View File

@ -0,0 +1,33 @@
package com.eleadmin.common.distributiondeviceinfo.domain.form;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* 配电设备新投异动图模维护信息表 关联信息查询表单
*
* @Author 王益亭
* @Date 2025-02-28 14:39:52
* @Copyright gxrd
*/
@Data
public class DistributionDeviceInfoLinkQueryForm {
@Schema(description = "计划工作大馈线")
@NotBlank
private String planWorkFeeder;
@Schema(description = "计划工作时间")
@JsonFormat(pattern = "yyyy-MM-dd")
@NotNull
private LocalDate planWorkTime;
}

View File

@ -0,0 +1,20 @@
package com.eleadmin.common.distributiondeviceinfo.domain.form;
import lombok.Data;
import com.eleadmin.common.powerdebug.domain.entity.PowerDebugEntity;
/**
* 配电设备新投异动图模维护信息表 关联新建表单
*
* @Author 王益亭
* @Date 2025-02-28 14:39:52
* @Copyright gxrd
*/
@Data
public class DistributionDeviceInfoLinkUpdateForm {
private DistributionDeviceInfoUpdateForm left;
private PowerDebugEntity right;
}

View File

@ -0,0 +1,37 @@
package com.eleadmin.common.distributiondeviceinfo.domain.form;
import com.eleadmin.common.core.web.BaseParam;
import com.eleadmin.common.core.web.PageParam;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDate;
/**
* 配电设备新投异动图模维护信息表 分页查询表单
*
* @Author 王益亭
* @Date 2025-02-28 14:39:52
* @Copyright gxrd
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class DistributionDeviceInfoQueryForm extends BaseParam {
private Integer id;
private Integer outageId;
/**
* 计划工作时间
*/
private String planWorkTime;
/**
* 图模涉及大馈线名称
*/
private String lineName;
private Integer createUser;
}

View File

@ -0,0 +1,99 @@
package com.eleadmin.common.distributiondeviceinfo.domain.form;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.NotNull;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import lombok.Data;
import com.eleadmin.common.distributiondeviceinfo.domain.entity.DistributionDeviceInfoEntity;
import com.eleadmin.common.distributiondeviceinfo.domain.entity.NewDevice;
/**
* 配电设备新投异动图模维护信息表 更新表单
*
* @Author 王益亭
* @Date 2025-02-28 14:39:52
* @Copyright gxrd
*/
@Data
public class DistributionDeviceInfoUpdateForm {
@Schema(description = "记录ID")
@NotNull(message = "记录ID 不能为空")
private Integer id;
@Schema(description = "计划工作(送电)时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime scheduledWorkTime;
@Schema(description = "图模涉及大馈线名称")
private String lineName;
/**
* 是否涉及调试0否1是
*/
private Integer whetherDebug;
@Schema(description = "计划工作大馈线")
private String planWorkFeeder;
@Schema(description = "计划工作时间")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate planWorkTime;
@Schema(description = "OMS新投异动编号")
private String omsNumber;
@Schema(description = "主业工程名称")
private String mainProjectName;
@Schema(description = "主业工程编号")
private String mainProjectCode;
@Schema(description = "是否已推工程")
private Integer isMainProject;
@Schema(description = "运行单位推工程人")
private String operatingUnitContact;
@Schema(description = "客户工程名称")
private String customerProjectName;
@Schema(description = "客户工程编号")
private String customerProjectCode;
@Schema(description = "是否涉及主业实物ID扫码")
private Integer involvesPhysicalId;
@Schema(description = "运行单位扫码人")
private String operatingUnitScanner;
@Schema(description = "新增设备运行维护班组")
private List<NewDevice> newEquipmentMaintenance;
@Schema(description = "联系人及电话")
private String contactPerson;
@Schema(description = "专用设备进线电缆资产属性")
private String specialEquipmentCableAsset;
@Schema(description = "专用设备T接点开关、刀闸资产属性")
private String specialEquipmentTapSwitchAsset;
@Schema(description = "专用设备用户编号")
private String specialEquipmentUserCode;
@Schema(description = "大客户经理及联系方式")
private String majorCustomerContact;
@Schema(description = "附件")
private String attachment;
}

View File

@ -0,0 +1,81 @@
package com.eleadmin.common.distributiondeviceinfo.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.eleadmin.common.core.excel.convert.LocalDateTimeConverter;
import com.eleadmin.common.core.excel.convert.YesNoConverter;
import lombok.Data;
import com.eleadmin.common.distributiondeviceinfo.domain.entity.NewDevice;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
/**
* 配电设备新投异动图模维护信息表 列表VO
*
* @Author 王益亭
* @Date 2025-02-28 14:39:52
* @Copyright gxrd
*/
@Data
public class DistributionDeviceInfoExcelVO {
@ExcelProperty(value = "计划工作(送电)时间")
private LocalDateTime scheduledWorkTime;
@ExcelProperty("图模涉及大馈线名称")
private String lineName;
@ExcelProperty("计划工作大馈线")
private String planWorkFeeder;
@ExcelProperty(value = "计划工作时间")
private LocalDate planWorkTime;
@ExcelProperty("OMS新投异动编号")
private String omsNumber;
@ExcelProperty("主业工程名称")
private String mainProjectName;
@ExcelProperty("主业工程编号")
private String mainProjectCode;
@ExcelProperty(value = "是否已推工程", converter = YesNoConverter.class)
private Integer isMainProject;
@ExcelProperty("运行单位推工程人")
private String operatingUnitContact;
@ExcelProperty("客户工程名称")
private String customerProjectName;
@ExcelProperty("客户工程编号")
private String customerProjectCode;
@ExcelProperty(value = "是否涉及主业实物ID扫码", converter = YesNoConverter.class)
private Integer involvesPhysicalId;
@ExcelProperty("运行单位扫码人")
private String operatingUnitScanner;
@ExcelProperty(value = "新增设备运行维护班组")
private List<NewDevice> newEquipmentMaintenance;
@ExcelProperty("联系人及电话")
private String contactPerson;
@ExcelProperty("专用设备进线电缆资产属性")
private String specialEquipmentCableAsset;
@ExcelProperty("专用设备T接点开关、刀闸资产属性")
private String specialEquipmentTapSwitchAsset;
@ExcelProperty("专用设备用户编号")
private String specialEquipmentUserCode;
@ExcelProperty("大客户经理及联系方式")
private String majorCustomerContact;
}

View File

@ -0,0 +1,30 @@
package com.eleadmin.common.distributiondeviceinfo.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import com.eleadmin.common.distributiondeviceinfo.domain.entity.DistributionDeviceInfoEntity;
import com.eleadmin.common.distributiondeviceinfo.domain.entity.NewDevice;
import com.eleadmin.common.powerdebug.domain.entity.PowerDebugEntity;
import com.eleadmin.common.powerdebug.domain.vo.PowerDebugVO;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
/**
* 配电设备新投异动图模维护信息表 列表VO
*
* @Author 王益亭
* @Date 2025-02-28 14:39:52
* @Copyright gxrd
*/
@Data
public class DistributionDeviceInfoUpdateVO {
private DistributionDeviceInfoVO left;
private PowerDebugEntity right;
}

View File

@ -0,0 +1,125 @@
package com.eleadmin.common.distributiondeviceinfo.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import lombok.Data;
import com.eleadmin.common.distributiondeviceinfo.domain.entity.NewDevice;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 配电设备新投异动图模维护信息表 列表VO
*
* @Author 王益亭
* @Date 2025-02-28 14:39:52
* @Copyright gxrd
*/
@Data
public class DistributionDeviceInfoVO {
@Schema(description = "记录ID")
private Integer id;
@Schema(description = "计划工作(送电)时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime scheduledWorkTime;
@Schema(description = "计划工作大馈线")
private String planWorkFeeder;
@Schema(description = "计划工作时间")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate planWorkTime;
@Schema(description = "图模涉及大馈线名称")
private String lineName;
@Schema(description = "OMS新投异动编号")
private String omsNumber;
@Schema(description = "主业工程名称")
private String mainProjectName;
@Schema(description = "主业工程编号")
private String mainProjectCode;
@Schema(description = "是否已推工程")
private Integer isMainProject;
@Schema(description = "运行单位推工程人")
private String operatingUnitContact;
@Schema(description = "客户工程名称")
private String customerProjectName;
@Schema(description = "客户工程编号")
private String customerProjectCode;
@Schema(description = "是否涉及主业实物ID扫码")
private Integer involvesPhysicalId;
@Schema(description = "运行单位扫码人")
private String operatingUnitScanner;
@Schema(description = "新增设备运行维护班组")
private List<NewDevice> newEquipmentMaintenance;
@Schema(description = "联系人及电话")
private String contactPerson;
@Schema(description = "专用设备进线电缆资产属性")
private String specialEquipmentCableAsset;
@Schema(description = "专用设备T接点开关、刀闸资产属性")
private String specialEquipmentTapSwitchAsset;
@Schema(description = "专用设备用户编号")
private String specialEquipmentUserCode;
@Schema(description = "大客户经理及联系方式")
private String majorCustomerContact;
@Schema(description = "附件")
private String attachment;
@Schema(description = "附件")
private String attachmentName;
/**
* 是否涉及调试0否1是
*/
@Schema(description = "是否涉及调试0否1是")
private Integer whetherDebug;
/**
* 是否完成状态0否1是
*/
@Schema(description = "是否完成状态0否1是")
private Integer finishStatus;
/**
* 是否提交0否1是
*/
@Schema(description = "是否提交0否1是")
private Integer commitStatus;
/**
* 提交时间
*/
@Schema(description = "是否提交0否1是")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDateTime commitTime;
/**
* 创建人
*/
@Schema(description = "创建人")
private Integer createUser;
}

View File

@ -0,0 +1,48 @@
package com.eleadmin.common.distributiondeviceinfo.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Data
public class DistributionDeviceSimpleVO {
@Schema(description = "记录ID")
private Integer id;
@Schema(description = "计划工作时间")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate planWorkTime;
@Schema(description = "图模涉及大馈线名称")
private String lineName;
@Schema(description = "OMS新投异动编号")
private String omsNumber;
/**
* 是否提交0否1是
*/
@Schema(description = "是否提交0否1是")
private Integer commitStatus;
/**
* 提交时间
*/
@Schema(description = "是否提交0否1是")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDateTime commitTime;
/**
* 是否完成状态0否1是
*/
@Schema(description = "是否完成状态0否1是")
private Integer finishStatus;
/**
* 创建用户
*/
private Integer createUser;
}

View File

@ -0,0 +1,21 @@
package com.eleadmin.common.distributiondeviceinfo.manager;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.eleadmin.common.distributiondeviceinfo.dao.DistributionDeviceInfoDao;
import com.eleadmin.common.distributiondeviceinfo.domain.entity.DistributionDeviceInfoEntity;
import org.springframework.stereotype.Service;
/**
* 配电设备新投异动图模维护信息表 Manager
*
* @Author 王益亭
* @Date 2025-02-28 14:39:52
* @Copyright gxrd
*/
@Service
public class DistributionDeviceInfoManager extends ServiceImpl<DistributionDeviceInfoDao, DistributionDeviceInfoEntity> {
}

View File

@ -0,0 +1,401 @@
package com.eleadmin.common.distributiondeviceinfo.service;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ClassUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.converters.AutoConverter;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterKeyBuild;
import com.alibaba.excel.converters.ReadConverterContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.Cell;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.read.metadata.holder.ReadSheetHolder;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.eleadmin.common.core.Constants;
import com.eleadmin.common.core.exception.BusinessException;
import com.eleadmin.common.core.utils.ExcelMapReader;
import com.eleadmin.common.core.utils.SmartBeanUtil;
import com.eleadmin.common.core.web.ApiResult;
import com.eleadmin.common.core.web.PageParam;
import com.eleadmin.common.core.web.PageResult;
import com.eleadmin.common.distributiondeviceinfo.dao.DistributionDeviceInfoDao;
import com.eleadmin.common.distributiondeviceinfo.domain.entity.DistributionDeviceInfoEntity;
import com.eleadmin.common.distributiondeviceinfo.domain.form.DistributionDeviceInfoLinkAddForm;
import com.eleadmin.common.distributiondeviceinfo.domain.form.DistributionDeviceInfoLinkQueryForm;
import com.eleadmin.common.distributiondeviceinfo.domain.form.DistributionDeviceInfoLinkUpdateForm;
import com.eleadmin.common.distributiondeviceinfo.domain.form.DistributionDeviceInfoQueryForm;
import com.eleadmin.common.distributiondeviceinfo.domain.vo.DistributionDeviceInfoExcelVO;
import com.eleadmin.common.distributiondeviceinfo.domain.vo.DistributionDeviceInfoUpdateVO;
import com.eleadmin.common.distributiondeviceinfo.domain.vo.DistributionDeviceInfoVO;
import com.eleadmin.common.distributiondeviceinfo.domain.vo.DistributionDeviceSimpleVO;
import com.eleadmin.common.powerdebug.domain.entity.PowerDebugEntity;
import com.eleadmin.common.powerdebug.manager.PowerDebugManager;
import com.eleadmin.common.system.param.IdParam;
import com.eleadmin.common.system.service.FileRecordService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
/**
* 配电设备新投异动图模维护信息表 Service
*
* @Author 王益亭
* @Date 2025-02-28 14:39:52
* @Copyright gxrd
*/
@Service
public class DistributionDeviceInfoService {
@Resource
private DistributionDeviceInfoDao distributionDeviceInfoDao;
@Resource
private PowerDebugManager powerDebugManager;
@Resource
private FileRecordService fileRecordService;
/**
* 分页查询
*
* @param queryForm
* @return
*/
public PageResult<DistributionDeviceInfoVO> queryPage(DistributionDeviceInfoQueryForm queryForm) {
PageParam page = new PageParam(queryForm);
List<DistributionDeviceInfoVO> list = distributionDeviceInfoDao.queryPage(page, queryForm);
PageResult<DistributionDeviceInfoVO> pageResult = new PageResult<>(list,page.getTotal());
return pageResult;
}
public PageResult<DistributionDeviceSimpleVO> querySimplePage(DistributionDeviceInfoQueryForm queryForm) {
PageParam page = new PageParam(queryForm);
List<DistributionDeviceSimpleVO> list = distributionDeviceInfoDao.querySimplePage(page, queryForm);
PageResult<DistributionDeviceSimpleVO> pageResult = new PageResult<>(list,page.getTotal());
return pageResult;
}
/**
* 添加
*/
public ApiResult<String> add(DistributionDeviceInfoLinkAddForm addForm) {
DistributionDeviceInfoEntity distributionDeviceInfoEntity = SmartBeanUtil.copy(addForm.getLeft(), DistributionDeviceInfoEntity.class);
distributionDeviceInfoEntity.setCreateTime(LocalDateTime.now());
try {
distributionDeviceInfoDao.insert(distributionDeviceInfoEntity);
if (distributionDeviceInfoEntity.getId() != null && addForm.getRight() != null) {
PowerDebugEntity right = addForm.getRight();
right.setDdiId(distributionDeviceInfoEntity.getId());
powerDebugManager.saveOrUpdate(right);
}
} catch (Exception e) {
return new ApiResult<>(Constants.RESULT_ERROR_CODE, e.getMessage());
}
return ApiResult.ok();
}
/**
* 更新
*
* @param updateForm
* @return
*/
public ApiResult<String> update(DistributionDeviceInfoLinkUpdateForm updateForm,Integer createUser) {
DistributionDeviceInfoEntity entity = distributionDeviceInfoDao.selectById(updateForm.getLeft().getId());
if (createUser != null && entity.getCommitStatus() == 1){
throw new BusinessException("已提交,无法修改");
}
DistributionDeviceInfoEntity distributionDeviceInfoEntity = SmartBeanUtil.copy(updateForm.getLeft(), DistributionDeviceInfoEntity.class);
try {
distributionDeviceInfoDao.updateById(distributionDeviceInfoEntity);
if (distributionDeviceInfoEntity.getId() != null && updateForm.getRight() != null) {
powerDebugManager.saveOrUpdate(updateForm.getRight());
}
} catch (Exception e) {
throw new BusinessException(e.getMessage());
}
return ApiResult.ok();
}
/**
* 批量删除
*
* @param idList
* @return
*/
public ApiResult<?> batchDelete(List<Integer> idList) {
if (CollectionUtils.isEmpty(idList)) {
return ApiResult.ok();
}
distributionDeviceInfoDao.deleteBatchIds(idList);
return ApiResult.ok();
}
public void importFromExcel(MultipartFile file,Integer userId,Integer commitStatus) {
VerticalTableReadListener<DistributionDeviceInfoExcelVO> readListener = new VerticalTableReadListener<>(DistributionDeviceInfoExcelVO.class);
try {
EasyExcel.read(file.getInputStream(), (ReadListener) readListener).sheet().headRowNumber(1).doRead();
DistributionDeviceInfoExcelVO data = readListener.getData();
DistributionDeviceInfoEntity entity = SmartBeanUtil.copy(data, DistributionDeviceInfoEntity.class);
entity.setCommitStatus(commitStatus);
if (commitStatus != null){
entity.setCommitStatus(commitStatus);
entity.setCommitTime(LocalDateTime.now());
}
entity.setCreateUser(userId);
entity.setCreateTime(LocalDateTime.now());
distributionDeviceInfoDao.insert(entity);
powerDebugManager.update(
Wrappers.lambdaUpdate(PowerDebugEntity.class)
.eq(PowerDebugEntity::getPlannedTestDate, entity.getPlanWorkTime())
.eq(PowerDebugEntity::getLineName, entity.getPlanWorkFeeder())
.set(PowerDebugEntity::getDdiId, entity.getId())
);
} catch (Exception e) {
System.out.println(e.getMessage());
throw new BusinessException();
}
}
public PowerDebugEntity queryLink(DistributionDeviceInfoLinkQueryForm queryForm) {
return powerDebugManager.getOne(
Wrappers.lambdaUpdate(PowerDebugEntity.class)
.eq(PowerDebugEntity::getPlannedTestDate, queryForm.getPlanWorkTime())
.eq(PowerDebugEntity::getLineName, queryForm.getPlanWorkFeeder())
.last("limit 1")
);
}
public DistributionDeviceInfoUpdateVO getById(Integer id) {
DistributionDeviceInfoUpdateVO vo = new DistributionDeviceInfoUpdateVO();
var form = new DistributionDeviceInfoQueryForm();
form.setPage(1L);
form.setLimit(1L);
form.setId(id);
PageParam<DistributionDeviceInfoEntity, DistributionDeviceInfoQueryForm> page = new PageParam<>(form);
distributionDeviceInfoDao.queryPage(page, form).stream().findFirst().ifPresent(vo::setLeft);
powerDebugManager.getOneOpt(Wrappers.lambdaQuery(PowerDebugEntity.class).eq(PowerDebugEntity::getDdiId, id).last("limit 1")).ifPresent(vo::setRight);
return vo;
}
public ApiResult<?> delete(Integer id) {
return distributionDeviceInfoDao.deleteById(id) > 0 ? ApiResult.ok() : ApiResult.fail();
}
public void commit(IdParam idParam) {
DistributionDeviceInfoEntity entity = distributionDeviceInfoDao.selectById(idParam.getId());
if (entity.getCommitStatus() == 1){
throw new BusinessException("请勿重复提交");
}
DistributionDeviceInfoEntity distributionDeviceInfoEntity = new DistributionDeviceInfoEntity();
distributionDeviceInfoEntity.setCommitStatus(1);
distributionDeviceInfoEntity.setCommitTime(LocalDateTime.now());
distributionDeviceInfoEntity.setId(idParam.getId());
distributionDeviceInfoDao.updateById(distributionDeviceInfoEntity);
}
public void repealCommit(IdParam idParam) {
DistributionDeviceInfoEntity distributionDeviceInfoEntity = new DistributionDeviceInfoEntity();
distributionDeviceInfoEntity.setCommitStatus(0);
distributionDeviceInfoEntity.setId(idParam.getId());
distributionDeviceInfoDao.updateById(distributionDeviceInfoEntity);
}
public Map<String, List<Map<String, Object>>> getExcel(Integer id) throws IOException {
DistributionDeviceInfoEntity distributionDeviceInfoEntity = distributionDeviceInfoDao.selectById(id);
if (StringUtils.isEmpty(distributionDeviceInfoEntity.getAttachment())){
throw new BusinessException("没有附件");
}
File file = new File(fileRecordService.getUploadDir(), distributionDeviceInfoEntity.getAttachment());
ExcelMapReader excelMapReader = new ExcelMapReader();
Map<String, List<Map<String, Object>>> stringListMap = excelMapReader.readAllSheets(file);
return stringListMap;
}
@Slf4j
public static class VerticalTableReadListener<T> implements ReadListener<Object> {
private final T excelVO;
private final Map<CharSequence, Tree<String>> fields;
private Map<ConverterKeyBuild.ConverterKey, Converter<?>> converterMap;
private String[] childHeadName = null;
private ReadCellData<?> head;
@SneakyThrows
public VerticalTableReadListener(Class<T> clazz) {
excelVO = clazz.getConstructor().newInstance();
fields = initializeFields(excelVO.getClass());
}
private void processChildNodes(Tree<String> tree, Field field, List<ReadCellData<?>> values, AnalysisContext analysisContext) {
if (childHeadName == null) {
childHeadName = new String[]{values.get(0).getStringValue(),values.get(1).getStringValue()};
return;
}
List<Tree<String>> children = tree.getChildren();
Map<CharSequence, Tree<String>> collect = children.stream().collect(Collectors.toMap(Tree::getName, Function.identity()));
try {
Object instance = getRealType(field).getConstructor().newInstance();
if (values.get(0) != null && !values.get(0).getType().equals(CellDataTypeEnum.EMPTY)) {
Tree<String> tree1 = collect.get(childHeadName[0]);
extracted(analysisContext, instance, values.get(0), (Field) tree1.get("field"), (ExcelProperty) tree1.get("anno"));
}
if (values.get(1) != null && !values.get(1).getType().equals(CellDataTypeEnum.EMPTY)) {
Tree<String> tree2 = collect.get(childHeadName[1]);
extracted(analysisContext, instance, values.get(1), (Field) tree2.get("field"), (ExcelProperty) tree2.get("anno"));
}
Object object = field.get(excelVO);
if (object == null) {
field.setAccessible(true);
object = new ArrayList<>();
field.set(excelVO, object);
}
((List<Object>) object).add(instance);
} catch (Exception e) {
log.error(e.getMessage(),e);
throw new RuntimeException(e);
}
}
private void extracted(AnalysisContext analysisContext, Object vo, ReadCellData<?> cellData, Field field, ExcelProperty property) {
try{
Class<? extends Converter<?>> converterClazz = property.converter();
Converter<?> converter;
if (converterClazz == AutoConverter.class) {
converter = converterMap.get(ConverterKeyBuild.buildKey(field.getType(), cellData.getType()));
} else {
converter = converterClazz.getConstructor().newInstance();
}
field.setAccessible(true);
field.set(vo, converter.convertToJavaData(new ReadConverterContext<>(cellData, null, analysisContext)));
}catch (Exception e) {
log.error(e.getMessage(),e);
throw new RuntimeException(e);
}
}
private static Map<CharSequence, Tree<String>> initializeFields(Class<?> clazz) {
return Arrays.stream(ClassUtil.getDeclaredFields(clazz))
.map(it -> {
ExcelProperty annotation = it.getAnnotation(ExcelProperty.class);
Tree<String> node = TreeUtil.createEmptyNode("");
node.setName(annotation.value()[0]);
node.put("field", it);
node.put("anno", annotation);
Class<?> realType = getRealType(it);
if (!ClassUtil.isJdkClass(realType) && ClassUtil.getPackage(realType).startsWith("com.eleadmin")) {
List<Tree<String>> list = Arrays.stream(ClassUtil.getDeclaredFields(realType))
.map(item -> {
ExcelProperty anno = item.getAnnotation(ExcelProperty.class);
Tree<String> nodes = TreeUtil.createEmptyNode("");
nodes.setName(anno.value()[0]);
nodes.put("field", item);
nodes.put("anno", anno);
nodes.setParent(node);
return nodes;
}).toList();
node.setChildren(list);
}
return node;
})
.collect(Collectors.toMap(Tree::getName, it -> it));
}
private static Class<?> getRealType(Field field) {
Type genericType = field.getGenericType();
Class<?> actualType;
if (genericType instanceof ParameterizedType parameterizedType) {
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
actualType = (Class<?>) actualTypeArguments[0];
} else {
actualType = field.getType();
}
return actualType;
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
public T getData() {
return excelVO;
}
@Override
public void invoke(Object o, AnalysisContext analysisContext) {
if (converterMap == null) {
converterMap = analysisContext.currentReadHolder().converterMap();
}
Map<Integer, Cell> cellMap = analysisContext.readRowHolder().getCellMap();
if (cellMap.size() < 3) {
log.warn("Insufficient cells in the row, skipping processing.");
return;
}
ReadCellData<?> key = (ReadCellData<?>) cellMap.get(0);
List<ReadCellData<?>> values = Arrays.asList((ReadCellData<?>) cellMap.get(1), (ReadCellData<?>) cellMap.get(2));
if (key.getStringValue() != null) {
head = key;
}
if (head == null) {
log.warn("Head cell is null, skipping processing.");
return;
}
Tree<String> tree = fields.get(head.getStringValue());
if (tree == null) {
log.warn("Field not found for head value: {}", head.getStringValue());
return;
}
Field field = (Field) tree.get("field");
field.setAccessible(true);
if (tree.hasChild()) {
processChildNodes(tree, field, values, analysisContext);
} else {
if (values.get(0) == null || values.get(0).getType().equals(CellDataTypeEnum.EMPTY)) {
return;
}
extracted(analysisContext, excelVO, values.get(0), field, (ExcelProperty) tree.get("anno"));
}
}
}
}

View File

@ -0,0 +1,22 @@
# 默认是按前端工程文件的 /views/business 文件夹的路径作为前端组件路径,如果你没把生成的 .vue 前端代码放在 /views/business 下,
# 那就根据自己实际情况修改下面 SQL 的 path,component 字段值,避免执行 SQL 后菜单无法访问。
# 如果你一切都是按照默认,那么下面的 SQL 基本不用改
INSERT INTO t_menu ( menu_name, menu_type, parent_id, path, component, frame_flag, cache_flag, visible_flag, disabled_flag, perms_type, create_user_id )
VALUES ( '新投异动', 2, 0, '/distribution-device-info/list', '/business/distribution-device-info/distribution-device-info-list.vue', false, false, true, false, 1, 1 );
# 按菜单名称查询该菜单的 menu_id 作为按钮权限的 父菜单ID 与 功能点关联菜单ID
SET @parent_id = NULL;
SELECT t_menu.menu_id INTO @parent_id FROM t_menu WHERE t_menu.menu_name = '新投异动';
INSERT INTO t_menu ( menu_name, menu_type, parent_id, frame_flag, cache_flag, visible_flag, disabled_flag, api_perms, perms_type, context_menu_id, create_user_id )
VALUES ( '查询', 3, @parent_id, false, true, true, false, 'distributionDeviceInfo:query', 1, @parent_id, 1 );
INSERT INTO t_menu ( menu_name, menu_type, parent_id, frame_flag, cache_flag, visible_flag, disabled_flag, api_perms, perms_type, context_menu_id, create_user_id )
VALUES ( '添加', 3, @parent_id, false, true, true, false, 'distributionDeviceInfo:add', 1, @parent_id, 1 );
INSERT INTO t_menu ( menu_name, menu_type, parent_id, frame_flag, cache_flag, visible_flag, disabled_flag, api_perms, perms_type, context_menu_id, create_user_id )
VALUES ( '更新', 3, @parent_id, false, true, true, false, 'distributionDeviceInfo:update', 1, @parent_id, 1 );
INSERT INTO t_menu ( menu_name, menu_type, parent_id, frame_flag, cache_flag, visible_flag, disabled_flag, api_perms, perms_type, context_menu_id, create_user_id )
VALUES ( '删除', 3, @parent_id, false, true, true, false, 'distributionDeviceInfo:delete', 1, @parent_id, 1 );

View File

@ -0,0 +1,9 @@
package com.eleadmin.common.faLine.Param;
import com.eleadmin.common.core.web.BaseParam;
import lombok.Data;
@Data
public class FaLineParam extends BaseParam {
private String lineName;
}

View File

@ -0,0 +1,66 @@
package com.eleadmin.common.faLine.controller;
import com.eleadmin.common.core.web.ApiResult;
import com.eleadmin.common.core.web.BaseController;
import com.eleadmin.common.distributiondeviceinfo.domain.form.DistributionDeviceInfoQueryForm;
import com.eleadmin.common.faLine.Param.FaLineParam;
import com.eleadmin.common.faLine.entity.FaLine;
import com.eleadmin.common.faLine.service.IFaLineService;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import java.util.stream.Collectors;
/**
* fa线路 前端控制器
*
* @author zg
* @since 2025-03-20
*/
@RestController
@RequestMapping("/api/faLine")
public class FaLineController extends BaseController {
@Resource
private IFaLineService service;
@Operation(summary = "分页查询")
@GetMapping("/queryPage")
@PreAuthorize("hasAuthority('faLine:query')")
public ApiResult queryPage(FaLineParam faLineParam) {
return success(service.queryPage(faLineParam));
}
@Operation(summary = "详情")
@GetMapping("/{id}")
@PreAuthorize("hasAuthority('faLine:query')")
public ApiResult getById(@PathVariable Integer id) {
return success(service.getById(id));
}
@Operation(summary = "新增")
@PostMapping("")
@PreAuthorize("hasAuthority('faLine:add')")
public ApiResult save(@RequestBody FaLine faLine) {
return service.save(faLine) ? success() : fail();
}
@Operation(summary = "修改")
@PutMapping("")
@PreAuthorize("hasAuthority('faLine:update')")
public ApiResult update(@RequestBody FaLine faLine) {
return service.updateById(faLine) ? success() : fail();
}
@Operation(summary = "删除")
@DeleteMapping("{id}")
@PreAuthorize("hasAuthority('faLine:remove')")
public ApiResult remove(@PathVariable Integer id) {
return service.removeById(id) ? success() : fail();
}
}

View File

@ -0,0 +1,32 @@
package com.eleadmin.common.faLine.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* fa线路
* </p>
*
* @author zg
* @since 2025-03-20
*/
@Getter
@Setter
@TableName("t_fa_line")
public class FaLine implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 图模涉及大馈线名称
*/
private String lineName;
}

View File

@ -0,0 +1,22 @@
package com.eleadmin.common.faLine.mapper;
import com.eleadmin.common.core.web.PageParam;
import com.eleadmin.common.faLine.Param.FaLineParam;
import com.eleadmin.common.faLine.entity.FaLine;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* fa线路 Mapper 接口
* </p>
*
* @author zg
* @since 2025-03-20
*/
public interface FaLineMapper extends BaseMapper<FaLine> {
List<FaLine> queryPage(PageParam page,@Param("param") FaLineParam faLineParam);
}

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.eleadmin.common.faLine.mapper.FaLineMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.eleadmin.common.faLine.entity.FaLine">
<id column="id" property="id" />
<result column="line_name" property="lineName" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, line_name
</sql>
<select id="queryPage" resultMap="BaseResultMap">
select id,line_name from t_fa_line
<where>
<if test="param.lineName != null and param.lineName != ''">
AND INSTR(t_fa_line.line_name,#{param.lineName})
</if>
</where>
</select>
</mapper>

View File

@ -0,0 +1,19 @@
package com.eleadmin.common.faLine.service;
import com.eleadmin.common.core.web.PageResult;
import com.eleadmin.common.faLine.Param.FaLineParam;
import com.eleadmin.common.faLine.entity.FaLine;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* fa线路 服务类
* </p>
*
* @author zg
* @since 2025-03-20
*/
public interface IFaLineService extends IService<FaLine> {
PageResult queryPage(FaLineParam faLineParam);
}

View File

@ -0,0 +1,31 @@
package com.eleadmin.common.faLine.service.impl;
import com.eleadmin.common.core.web.PageParam;
import com.eleadmin.common.core.web.PageResult;
import com.eleadmin.common.faLine.Param.FaLineParam;
import com.eleadmin.common.faLine.entity.FaLine;
import com.eleadmin.common.faLine.mapper.FaLineMapper;
import com.eleadmin.common.faLine.service.IFaLineService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* <p>
* fa线路 服务实现类
* </p>
*
* @author zg
* @since 2025-03-20
*/
@Service
public class FaLineServiceImpl extends ServiceImpl<FaLineMapper, FaLine> implements IFaLineService {
@Override
public PageResult queryPage(FaLineParam faLineParam) {
PageParam page = new PageParam(faLineParam);
List<FaLine> list = baseMapper.queryPage(page,faLineParam);
return new PageResult(list,page.getTotal());
}
}

View File

@ -0,0 +1,69 @@
package com.eleadmin.common.flowStep.controller;
import com.eleadmin.common.core.web.ApiResult;
import com.eleadmin.common.core.web.BaseController;
import com.eleadmin.common.flowStep.entity.Field;
import com.eleadmin.common.flowStep.entity.Flow;
import com.eleadmin.common.flowStep.entity.param.FieldParam;
import com.eleadmin.common.flowStep.entity.param.FlowParam;
import com.eleadmin.common.flowStep.service.IFieldService;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.time.LocalDateTime;
/**
* 流程字段 前端控制器
*
* @author zg
* @since 2025-03-24
*/
@RestController
@RequestMapping("/api/field")
public class FieldController extends BaseController {
@Resource
private IFieldService service;
@Operation(summary = "分页查询")
@GetMapping("/queryPage")
@PreAuthorize("hasAuthority('field:query')")
public ApiResult queryPage(FieldParam fieldParam) {
return success(service.queryPage(fieldParam));
}
@Operation(summary = "详情")
@GetMapping("/{id}")
@PreAuthorize("hasAuthority('field:query')")
public ApiResult getById(@PathVariable Integer id) {
return success(service.getById(id));
}
@Operation(summary = "新增")
@PostMapping("")
@PreAuthorize("hasAuthority('field:add')")
public ApiResult save(@RequestBody Field entity) {
entity.setCreateTime(LocalDateTime.now());
entity.setCreateUser(getLoginUserId());
return service.save(entity) ? success() : fail();
}
@Operation(summary = "修改")
@PutMapping("")
@PreAuthorize("hasAuthority('field:update')")
public ApiResult update(@RequestBody Field entity) {
entity.setCreateTime(null);
entity.setCreateUser(null);
return service.updateById(entity) ? success() : fail();
}
@Operation(summary = "删除")
@DeleteMapping("{id}")
@PreAuthorize("hasAuthority('field:remove')")
public ApiResult remove(@PathVariable Integer id) {
return service.removeById(id) ? success() : fail();
}
}

View File

@ -0,0 +1,73 @@
package com.eleadmin.common.flowStep.controller;
import com.eleadmin.common.core.web.ApiResult;
import com.eleadmin.common.core.web.BaseController;
import com.eleadmin.common.faLine.Param.FaLineParam;
import com.eleadmin.common.faLine.entity.FaLine;
import com.eleadmin.common.faLine.service.IFaLineService;
import com.eleadmin.common.flowStep.entity.Flow;
import com.eleadmin.common.flowStep.entity.param.FlowParam;
import com.eleadmin.common.flowStep.service.IFlowService;
import io.swagger.annotations.OAuth2Definition;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.time.LocalDateTime;
/**
* 流程主表 前端控制器
*
* @author zg
* @since 2025-03-24
*/
@RestController
@RequestMapping("/api/flow")
public class FlowController extends BaseController {
@Resource
private IFlowService service;
@Operation(summary = "分页查询")
@GetMapping("/queryPage")
@PreAuthorize("hasAuthority('flow:query')")
public ApiResult queryPage(FlowParam flowParam) {
return success(service.queryPage(flowParam));
}
@Operation(summary = "详情")
@GetMapping("/{id}")
@PreAuthorize("hasAuthority('flow:query')")
public ApiResult getById(@PathVariable Integer id) {
return success(service.getById(id));
}
@Operation(summary = "新增")
@PostMapping("")
@PreAuthorize("hasAuthority('flow:add')")
public ApiResult save(@RequestBody Flow flow) {
flow.setCreateTime(LocalDateTime.now());
flow.setCreateUser(getLoginUserId());
return service.save(flow) ? success() : fail();
}
@Operation(summary = "修改")
@PutMapping("")
@PreAuthorize("hasAuthority('flow:update')")
public ApiResult update(@RequestBody Flow flow) {
flow.setCreateTime(null);
flow.setCreateUser(null);
return service.updateById(flow) ? success() : fail();
}
@Operation(summary = "删除")
@DeleteMapping("{id}")
@PreAuthorize("hasAuthority('flow:remove')")
public ApiResult remove(@PathVariable Integer id) {
return service.removeById(id) ? success() : fail();
}
}

View File

@ -0,0 +1,95 @@
package com.eleadmin.common.flowStep.controller;
import cn.hutool.core.codec.Base16Codec;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.eleadmin.common.core.web.ApiResult;
import com.eleadmin.common.core.web.BaseController;
import com.eleadmin.common.flowStep.entity.Field;
import com.eleadmin.common.flowStep.entity.Step;
import com.eleadmin.common.flowStep.entity.param.FieldParam;
import com.eleadmin.common.flowStep.entity.param.StepParam;
import com.eleadmin.common.flowStep.service.IFieldService;
import com.eleadmin.common.flowStep.service.IStepService;
import com.eleadmin.common.system.service.RoleService;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.time.LocalDateTime;
/**
* 步骤表 前端控制器
*
* @author zg
* @since 2025-03-24
*/
@RestController
@RequestMapping("/api/step")
public class StepController extends BaseController {
@Resource
private IStepService service;
@Resource
private RoleService roleService;
@Resource
private IFieldService fieldService;
@Operation(summary = "分页查询")
@GetMapping("/queryPage")
@PreAuthorize("hasAuthority('field:query')")
public ApiResult queryPage(StepParam param) {
return success(service.queryPage(param));
}
@Operation(summary = "详情")
@GetMapping("/{id}")
@PreAuthorize("hasAuthority('field:query')")
public ApiResult getById(@PathVariable Integer id) {
return success(service.getById(id));
}
@Operation(summary = "角色下拉")
@GetMapping("getRoles")
@PreAuthorize("hasAuthority('field:add')")
public ApiResult getRole() {
return success( roleService.list());
}
@Operation(summary = "字段下拉")
@GetMapping("getFields")
@PreAuthorize("hasAuthority('field:add')")
public ApiResult getFields(FieldParam fieldParam) {
return success( fieldService.getFields(fieldParam));
}
@Operation(summary = "新增")
@PostMapping("")
@PreAuthorize("hasAuthority('field:add')")
public ApiResult save(@RequestBody Step entity) {
if (entity.getStepNumber() == null){
Long count = service.count(Wrappers.lambdaQuery(Step.class).eq(Step::getFlowId, entity.getFlowId()));
entity.setStepNumber(Integer.parseInt(count.toString()) + 1);
}
entity.setCreateTime(LocalDateTime.now());
entity.setCreateUser(getLoginUserId());
return service.save(entity) ? success() : fail();
}
@Operation(summary = "修改")
@PutMapping("")
@PreAuthorize("hasAuthority('field:update')")
public ApiResult update(@RequestBody Step entity) {
entity.setCreateTime(null);
entity.setCreateUser(null);
return service.updateById(entity) ? success() : fail();
}
@Operation(summary = "删除")
@DeleteMapping("{id}")
@PreAuthorize("hasAuthority('field:remove')")
public ApiResult remove(@PathVariable Integer id) {
return service.removeById(id) ? success() : fail();
}
}

View File

@ -0,0 +1,16 @@
package com.eleadmin.common.flowStep.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 停电步骤表 前端控制器
*
* @author zg
* @since 2025-03-24
*/
@RestController
@RequestMapping("/stepTable")
public class StepTableController {
}

View File

@ -0,0 +1,16 @@
package com.eleadmin.common.flowStep.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 停电步骤字段表 前端控制器
*
* @author zg
* @since 2025-03-24
*/
@RestController
@RequestMapping("/stepTableField")
public class StepTableFieldController {
}

View File

@ -0,0 +1,60 @@
package com.eleadmin.common.flowStep.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 流程字段
* </p>
*
* @author zg
* @since 2025-03-24
*/
@Getter
@Setter
@TableName("f_field")
public class Field implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 字段名称
*/
private String fieldTitle;
/**
* 字段key
*/
private String fieldKey;
/**
* 字段类型
*/
private String fieldType;
/**
* 创建用户
*/
private Integer createUser;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 逻辑删除
*/
@TableLogic(value = "0",delval = "1")
private Integer deleted;
}

View File

@ -0,0 +1,53 @@
package com.eleadmin.common.flowStep.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* 流程主表
*
* @author zg
* @since 2025-03-24
*/
@Getter
@Setter
@TableName("f_flow")
public class Flow implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 流程名称
*/
private String title;
/**
* 是否启用0未启用1启用
*/
private Integer enable;
/**
* 创建人
*/
private Integer createUser;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 逻辑删除0未删除
*/
@TableLogic(value = "0",delval = "1")
private Integer deleted;
}

View File

@ -0,0 +1,70 @@
package com.eleadmin.common.flowStep.entity;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 步骤表
* </p>
*
* @author zg
* @since 2025-03-24
*/
@Getter
@Setter
@TableName("f_step")
public class Step implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 流程id
*/
private Integer flowId;
/**
* 步骤名称
*/
private String stepTitle;
/**
* 字段ids
*/
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String fieldIds;
/**
* 角色ids
*/
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String strIds;
/**
* 步骤号
*/
private Integer stepNumber;
/**
* 逻辑删除
*/
@TableLogic(value = "0",delval = "1")
private Integer deleted;
/**
* 创建用户
*/
private Integer createUser;
/**
* 创建时间
*/
private LocalDateTime createTime;
}

View File

@ -0,0 +1,82 @@
package com.eleadmin.common.flowStep.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import com.eleadmin.common.outagework.domain.entity.OutageWorkEntity;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 停电步骤表
* </p>
*
* @author zg
* @since 2025-03-24
*/
@Getter
@Setter
@TableName("f_step_table")
public class StepTable implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 停电计划id
*/
private Integer outageId;
/**
* 步骤id
*/
private Integer stepId;
/**
* 步骤号
*/
private Integer stepNumber;
/**
* 步骤名称
*/
private String stepTitle;
/**
* 字段ids
*/
private String fieldIds;
/**
* 创建用户
*/
private Integer createUser;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 逻辑删除
*/
@TableLogic(value = "0",delval = "1")
private Integer deleted;
public StepTable(OutageWorkEntity outageWorkEntity,Step step,Integer userId) {
this.outageId = outageWorkEntity.getId();
this.stepTitle = step.getStepTitle();
this.stepNumber = step.getStepNumber();
this.stepId = step.getId();
this.fieldIds= step.getFieldIds();
this.createTime = LocalDateTime.now();
this.createUser = userId;
}
}

View File

@ -0,0 +1,72 @@
package com.eleadmin.common.flowStep.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 停电步骤字段表
* </p>
*
* @author zg
* @since 2025-03-24
*/
@Getter
@Setter
@TableName("f_step_table_field")
public class StepTableField implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 停电步骤id
*/
private Integer stepTableId;
/**
* 字段id
*/
private Integer fieldId;
/**
* 字段类型
*/
private String fieldType;
/**
* 字段名称
*/
private String fieldTitle;
/**
* 字段key
*/
private String fieldKey;
/**
* 字段值
*/
private String fieldValue;
/**
* 逻辑删除
*/
@TableLogic(value = "0",delval = "1")
private Integer deleted;
public StepTableField(Integer stepTableId,Field field,String fieldValue) {
this.stepTableId = stepTableId;
this.fieldId = field.getId();
this.fieldKey = field.getFieldKey();
this.fieldTitle = field.getFieldTitle();
this.fieldType = field.getFieldType();
this.fieldValue = fieldValue;
}
}

View File

@ -0,0 +1,23 @@
package com.eleadmin.common.flowStep.entity.param;
import com.eleadmin.common.core.web.BaseParam;
import lombok.Data;
@Data
public class FieldParam extends BaseParam {
/**
* 字段名称
*/
private String fieldTitle;
/**
* 字段key
*/
private String fieldKey;
/**
* 字段类型
*/
private String fieldType;
}

View File

@ -0,0 +1,10 @@
package com.eleadmin.common.flowStep.entity.param;
import com.eleadmin.common.core.web.BaseParam;
import lombok.Data;
@Data
public class FlowParam extends BaseParam {
private String title;
}

View File

@ -0,0 +1,17 @@
package com.eleadmin.common.flowStep.entity.param;
import com.eleadmin.common.core.web.BaseParam;
import lombok.Data;
@Data
public class StepParam extends BaseParam {
/**
* 流程id
*/
private Integer flowId;
/**
* 步骤名称
*/
private String stepTitle;
}

View File

@ -0,0 +1,37 @@
package com.eleadmin.common.flowStep.entity.vo;
import lombok.Data;
@Data
public class StepTableFieldVo {
private Integer id;
/**
* 停电步骤id
*/
private Integer stepTableId;
/**
* 字段id
*/
private Integer fieldId;
/**
* 字段类型
*/
private String fieldType;
/**
* 字段名称
*/
private String fieldTitle;
/**
* 字段key
*/
private String fieldKey;
/**
* 字段值
*/
private String fieldValue;
}

View File

@ -0,0 +1,36 @@
package com.eleadmin.common.flowStep.entity.vo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.util.List;
@Data
public class StepTableVo {
/**
* 步骤id
*/
private Integer stepId;
/**
* 停电步骤id
*/
private Integer stepTableId;
/**
* 停电计划id
*/
private Integer outageId;
/**
* 步骤号
*/
private Integer stepNumber;
/**
* 步骤名称
*/
private String stepTitle;
private List<StepTableFieldVo> fieldlist;
}

View File

@ -0,0 +1,25 @@
package com.eleadmin.common.flowStep.mapper;
import com.eleadmin.common.core.web.PageParam;
import com.eleadmin.common.flowStep.entity.Field;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.eleadmin.common.flowStep.entity.param.FieldParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* <p>
* 流程字段 Mapper 接口
* </p>
*
* @author zg
* @since 2025-03-24
*/
public interface FieldMapper extends BaseMapper<Field> {
List<Map<String, Object>> queryPage(@Param("page") PageParam page,@Param("param") FieldParam param);
List<Map<String, Object>> getFields(@Param("param") FieldParam fieldParam);
}

View File

@ -0,0 +1,23 @@
package com.eleadmin.common.flowStep.mapper;
import com.eleadmin.common.core.web.PageParam;
import com.eleadmin.common.flowStep.entity.Flow;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.eleadmin.common.flowStep.entity.param.FlowParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* <p>
* 流程主表 Mapper 接口
* </p>
*
* @author zg
* @since 2025-03-24
*/
public interface FlowMapper extends BaseMapper<Flow> {
List<Map<String, Object>> queryPage(@Param("page") PageParam page,@Param("param") FlowParam param);
}

View File

@ -0,0 +1,23 @@
package com.eleadmin.common.flowStep.mapper;
import com.eleadmin.common.core.web.PageParam;
import com.eleadmin.common.flowStep.entity.Step;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.eleadmin.common.flowStep.entity.param.StepParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* <p>
* 步骤表 Mapper 接口
* </p>
*
* @author zg
* @since 2025-03-24
*/
public interface StepMapper extends BaseMapper<Step> {
List<Map<String, Object>> queryPage(@Param("page") PageParam page,@Param("param") StepParam param);
}

View File

@ -0,0 +1,21 @@
package com.eleadmin.common.flowStep.mapper;
import com.eleadmin.common.flowStep.entity.StepTableField;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.eleadmin.common.flowStep.entity.vo.StepTableFieldVo;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* 停电步骤字段表 Mapper 接口
* </p>
*
* @author zg
* @since 2025-03-24
*/
public interface StepTableFieldMapper extends BaseMapper<StepTableField> {
List<StepTableFieldVo> getFlowFieldList(@Param("stepTableId") Integer stepTableId);
}

View File

@ -0,0 +1,22 @@
package com.eleadmin.common.flowStep.mapper;
import com.eleadmin.common.flowStep.entity.StepTable;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.eleadmin.common.flowStep.entity.vo.StepTableVo;
import org.apache.ibatis.annotations.Param;
import org.springframework.security.core.parameters.P;
import java.util.List;
/**
* <p>
* 停电步骤表 Mapper 接口
* </p>
*
* @author zg
* @since 2025-03-24
*/
public interface StepTableMapper extends BaseMapper<StepTable> {
List<StepTableVo> getFlowList(@Param("id") Integer id,@Param("whetherDebug") Integer whetherDebug);
}

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.eleadmin.common.flowStep.mapper.FieldMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.eleadmin.common.flowStep.entity.Field">
<id column="id" property="id" />
<result column="field_title" property="fieldTitle" />
<result column="field_key" property="fieldKey" />
<result column="field_type" property="fieldType" />
<result column="create_user" property="createUser" />
<result column="create_time" property="createTime" />
<result column="deleted" property="deleted" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, field_title, field_key, field_type, create_user, create_time, deleted
</sql>
<select id="queryPage" resultType="java.util.Map">
select id, field_title `fieldTitle`, field_key `fieldKey`, field_type `fieldType` from f_field fd
<where>
fd.deleted = 0
<if test="param.fieldTitle != null and param.fieldTitle != ''">
AND INSTR(fd.field_title,#{param.fieldTitle})
</if>
<if test="param.fieldKey != null and param.fieldKey != ''">
AND INSTR(fd.field_key,#{param.fieldKey})
</if>
<if test="param.fieldType != null and param.fieldType != ''">
AND INSTR(fd.field_type,#{param.fieldType})
</if>
</where>
order by id desc
</select>
<select id="getFields" resultType="java.util.Map">
select id, field_title `fieldTitle`, field_key `fieldKey`, field_type `fieldType` from f_field fd
<where>
fd.deleted = 0
<if test="param.fieldTitle != null and param.fieldTitle != ''">
AND INSTR(fd.field_title,#{param.fieldTitle})
</if>
<if test="param.fieldKey != null and param.fieldKey != ''">
AND INSTR(fd.field_key,#{param.fieldKey})
</if>
<if test="param.fieldType != null and param.fieldType != ''">
AND INSTR(fd.field_type,#{param.fieldType})
</if>
</where>
order by id desc
</select>
</mapper>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.eleadmin.common.flowStep.mapper.FlowMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.eleadmin.common.flowStep.entity.Flow">
<id column="id" property="id" />
<result column="title" property="title" />
<result column="enable" property="enable" />
<result column="create_user" property="createUser" />
<result column="create_time" property="createTime" />
<result column="deleted" property="deleted" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, title, enable, create_user, create_time, deleted
</sql>
<select id="queryPage" resultType="java.util.Map">
select id, title, enable from f_flow f
<where>
f.deleted = 0
<if test="param.title != null and param.title != ''">
AND INSTR(f.title,#{param.title})
</if>
</where>
order by f.id desc
</select>
</mapper>

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.eleadmin.common.flowStep.mapper.StepMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.eleadmin.common.flowStep.entity.Step">
<id column="id" property="id" />
<result column="flow_id" property="flowId" />
<result column="step_title" property="stepTitle" />
<result column="field_ids" property="fieldIds" />
<result column="str_ids" property="strIds" />
<result column="step_number" property="stepNumber" />
<result column="deleted" property="deleted" />
<result column="create_user" property="createUser" />
<result column="create_time" property="createTime" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, flow_id, step_title, field_ids, str_ids, step_number, deleted, create_user, create_time
</sql>
<select id="queryPage" resultType="java.util.Map">
select id,
flow_id `flowId`,
step_title `stepTitle`,
field_ids `fieldIds`,
str_ids `strIds`,
ifnull(step_number,'') `stepNumber`
from f_step fs
<where>
fs.deleted = 0
<if test="param.stepTitle != null and param.stepTitle != ''">
AND INSTR(fs.step_title,#{param.stepTitle})
</if>
<if test="param.flowId != null">
and fs.flow_id = #{param.flowId}
</if>
</where>
order by step_number
</select>
</mapper>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.eleadmin.common.flowStep.mapper.StepTableFieldMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.eleadmin.common.flowStep.entity.StepTableField">
<id column="id" property="id" />
<result column="field_id" property="fieldId" />
<result column="field_type" property="fieldType" />
<result column="field_title" property="fieldTitle" />
<result column="field_key" property="fieldKey" />
<result column="field_value" property="fieldValue" />
<result column="deleted" property="deleted" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, field_id, field_type, field_title, field_key, field_value, deleted
</sql>
<select id="getFlowFieldList" resultType="com.eleadmin.common.flowStep.entity.vo.StepTableFieldVo">
select id,step_table_id, field_id, field_type, field_title, field_key, field_value, deleted from f_step_table_field fstf
where step_table_id = #{stepTableId}
</select>
</mapper>

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.eleadmin.common.flowStep.mapper.StepTableMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.eleadmin.common.flowStep.entity.StepTable">
<id column="id" property="id" />
<result column="outage_id" property="outageId" />
<result column="step_id" property="stepId" />
<result column="step_number" property="stepNumber" />
<result column="step_name" property="stepName" />
<result column="field_ids" property="fieldIds" />
<result column="create_user" property="createUser" />
<result column="create_time" property="createTime" />
<result column="deleted" property="deleted" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, outage_id, step_id, step_number, step_name, field_ids, create_user, create_time, deleted
</sql>
<select id="getFlowList" resultType="com.eleadmin.common.flowStep.entity.vo.StepTableVo">
SELECT
fs.id `stepId`,
fst.id `stepTableId`,
fst.outage_id `outageId`,
IFnull( fst.step_title, fs.step_title ) `stepTitle`,
IFnull( fst.step_number, fs.step_number ) `stepNumber`
FROM
f_step fs
LEFT JOIN t_outage_work ow ON fs.flow_id = ow.flow_id
LEFT JOIN f_step_table fst ON fst.step_id = fs.id
AND ow.id = fst.outage_id
WHERE
fs.deleted = 0
<if test="id != null">
AND ow.id = #{id}
</if>
<if test="whetherDebug != null">
AND fs.step_number != #{whetherDebug}
</if>
ORDER BY
fs.step_number ASC
</select>
</mapper>

View File

@ -0,0 +1,24 @@
package com.eleadmin.common.flowStep.service;
import com.eleadmin.common.core.web.PageResult;
import com.eleadmin.common.flowStep.entity.Field;
import com.baomidou.mybatisplus.extension.service.IService;
import com.eleadmin.common.flowStep.entity.param.FieldParam;
import java.util.List;
import java.util.Map;
/**
* <p>
* 流程字段 服务类
* </p>
*
* @author zg
* @since 2025-03-24
*/
public interface IFieldService extends IService<Field> {
PageResult queryPage(FieldParam fieldParam);
List<Map<String,Object>> getFields(FieldParam fieldParam);
}

View File

@ -0,0 +1,19 @@
package com.eleadmin.common.flowStep.service;
import com.eleadmin.common.core.web.PageResult;
import com.eleadmin.common.flowStep.entity.Flow;
import com.baomidou.mybatisplus.extension.service.IService;
import com.eleadmin.common.flowStep.entity.param.FlowParam;
/**
* <p>
* 流程主表 服务类
* </p>
*
* @author zg
* @since 2025-03-24
*/
public interface IFlowService extends IService<Flow> {
PageResult queryPage(FlowParam flowParam);
}

View File

@ -0,0 +1,19 @@
package com.eleadmin.common.flowStep.service;
import com.eleadmin.common.core.web.PageResult;
import com.eleadmin.common.flowStep.entity.Step;
import com.baomidou.mybatisplus.extension.service.IService;
import com.eleadmin.common.flowStep.entity.param.StepParam;
/**
* <p>
* 步骤表 服务类
* </p>
*
* @author zg
* @since 2025-03-24
*/
public interface IStepService extends IService<Step> {
PageResult queryPage(StepParam param);
}

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