Compare commits

..

No commits in common. "master" and "v3.8.0" have entirely different histories.

272 changed files with 6337 additions and 12805 deletions

1
.github/FUNDING.yml vendored
View File

@ -1 +0,0 @@
custom: http://doc.ruoyi.vip/ruoyi-vue/other/donate.html

3
.gitignore vendored
View File

@ -25,9 +25,6 @@ target/
*.iml *.iml
*.ipr *.ipr
### JRebel ###
rebel.xml
### NetBeans ### ### NetBeans ###
nbproject/private/ nbproject/private/
build/* build/*

View File

@ -1,14 +1,3 @@
<p align="center">
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
</p>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.8.2</h1>
<h4 align="center">基于SpringBoot+Vue前后端分离的Java快速开发框架</h4>
<p align="center">
<a href="https://gitee.com/y_project/RuoYi-Vue/stargazers"><img src="https://gitee.com/y_project/RuoYi-Vue/badge/star.svg?theme=dark"></a>
<a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.8.2-brightgreen.svg"></a>
<a href="https://gitee.com/y_project/RuoYi-Vue/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
</p>
## 平台简介 ## 平台简介
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。 若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
@ -94,4 +83,4 @@
## 若依前后端分离交流群 ## 若依前后端分离交流群
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/已满-104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) [![加入QQ群](https://img.shields.io/badge/已满-186866453-blue.svg)](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [![加入QQ群](https://img.shields.io/badge/已满-201396349-blue.svg)](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [![加入QQ群](https://img.shields.io/badge/已满-101456076-blue.svg)](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [![加入QQ群](https://img.shields.io/badge/已满-101539465-blue.svg)](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [![加入QQ群](https://img.shields.io/badge/已满-264312783-blue.svg)](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [![加入QQ群](https://img.shields.io/badge/167385320-blue.svg)](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) 点击按钮入群。 QQ群 [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/已满-104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) [![加入QQ群](https://img.shields.io/badge/已满-186866453-blue.svg)](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [![加入QQ群](https://img.shields.io/badge/已满-201396349-blue.svg)](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [![加入QQ群](https://img.shields.io/badge/已满-101456076-blue.svg)](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [![加入QQ群](https://img.shields.io/badge/101539465-blue.svg)](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) 点击按钮入群。

33
demo/.gitignore vendored
View File

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

Binary file not shown.

View File

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

316
demo/mvnw vendored
View File

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

188
demo/mvnw.cmd vendored
View File

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

View File

@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

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

View File

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

31
pom.xml
View File

@ -6,26 +6,27 @@
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.8.2</version> <version>3.8.0</version>
<name>ruoyi</name> <name>ruoyi</name>
<url>http://www.ruoyi.vip</url> <url>http://www.ruoyi.vip</url>
<description>若依管理系统</description> <description>若依管理系统</description>
<properties> <properties>
<ruoyi.version>3.8.2</ruoyi.version> <ruoyi.version>3.8.0</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>11</java.version> <java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<druid.version>1.2.11</druid.version> <druid.version>1.2.8</druid.version>
<bitwalker.version>1.21</bitwalker.version> <bitwalker.version>1.21</bitwalker.version>
<swagger.version>3.0.0</swagger.version> <swagger.version>3.0.0</swagger.version>
<kaptcha.version>2.3.2</kaptcha.version> <kaptcha.version>2.3.2</kaptcha.version>
<mybatis-spring-boot.version>2.2.2</mybatis-spring-boot.version> <mybatis-spring-boot.version>2.2.0</mybatis-spring-boot.version>
<pagehelper.boot.version>1.4.2</pagehelper.boot.version> <pagehelper.boot.version>1.4.0</pagehelper.boot.version>
<fastjson.version>1.2.83</fastjson.version> <fastjson.version>1.2.78</fastjson.version>
<oshi.version>6.1.6</oshi.version> <oshi.version>5.8.2</oshi.version>
<jna.version>5.9.0</jna.version>
<commons.io.version>2.11.0</commons.io.version> <commons.io.version>2.11.0</commons.io.version>
<commons.fileupload.version>1.4</commons.fileupload.version> <commons.fileupload.version>1.4</commons.fileupload.version>
<commons.collections.version>3.2.2</commons.collections.version> <commons.collections.version>3.2.2</commons.collections.version>
@ -42,7 +43,7 @@
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId> <artifactId>spring-boot-dependencies</artifactId>
<version>2.5.14</version> <version>2.5.6</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
@ -82,6 +83,18 @@
<version>${oshi.version}</version> <version>${oshi.version}</version>
</dependency> </dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>${jna.version}</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>${jna.version}</version>
</dependency>
<!-- Swagger3依赖 --> <!-- Swagger3依赖 -->
<dependency> <dependency>
<groupId>io.springfox</groupId> <groupId>io.springfox</groupId>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.8.2</version> <version>3.8.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging> <packaging>jar</packaging>
@ -17,27 +17,7 @@
<dependencies> <dependencies>
<dependency> <!-- spring-boot-devtools -->
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.1</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId> <artifactId>spring-boot-devtools</artifactId>
@ -54,19 +34,7 @@
<dependency> <dependency>
<groupId>io.swagger</groupId> <groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId> <artifactId>swagger-models</artifactId>
<version>1.6.6</version> <version>1.6.2</version>
</dependency>
<!-- knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<!-- postgresql驱动包-->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.20</version>
</dependency> </dependency>
<!-- Mysql驱动包 --> <!-- Mysql驱动包 -->

View File

@ -1,6 +1,5 @@
package com.ruoyi; package com.ruoyi;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@ -11,25 +10,21 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
* @author ruoyi * @author ruoyi
*/ */
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@MapperScan("com.ruoyi.system.mapper_yada")
public class RuoYiApplication public class RuoYiApplication
{ {
public static void main(String[] args) public static void main(String[] args)
{ {
// System.setProperty("spring.devtools.restart.enabled", "false"); // System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(RuoYiApplication.class, args); SpringApplication.run(RuoYiApplication.class, args);
System.out.println(); System.out.println("(♥◠‿◠)ノ゙ 若依启动成功 ლ(´ڡ`ლ)゙ \n" +
System.out.println(" --->>>启动成功!<<<---"); " .-------. ____ __ \n" +
// System.out.println("(♥◠‿◠)ノ゙ ლ(´ڡ`ლ)゙ \n" + " | _ _ \\ \\ \\ / / \n" +
// " .-------. ____ __ \n" + " | ( ' ) | \\ _. / ' \n" +
// " | _ _ \\ \\ \\ / / \n" + " |(_ o _) / _( )_ .' \n" +
// " | ( ' ) | \\ _. / ' \n" + " | (_,_).' __ ___(_ o _)' \n" +
// " |(_ o _) / _( )_ .' \n" + " | |\\ \\ | || |(_,_)' \n" +
// " | (_,_).' __ ___(_ o _)' \n" + " | | \\ `' /| `-' / \n" +
// " | |\\ \\ | || |(_,_)' \n" + " | | \\ / \\ / \n" +
// " | | \\ `' /| `-' / \n" + " ''-' `'-' `-..-' ");
// " | | \\ / \\ / \n" +
// " ''-' `'-' `-..-' ");
} }
} }

View File

@ -0,0 +1,93 @@
package com.ruoyi.web.controller.common;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.common.config.RuoYiConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.google.code.kaptcha.Producer;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.sign.Base64;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.service.ISysConfigService;
/**
* 验证码操作处理
*
* @author ruoyi
*/
@RestController
public class CaptchaController
{
@Resource(name = "captchaProducer")
private Producer captchaProducer;
@Resource(name = "captchaProducerMath")
private Producer captchaProducerMath;
@Autowired
private RedisCache redisCache;
@Autowired
private ISysConfigService configService;
/**
* 生成验证码
*/
@GetMapping("/captchaImage")
public AjaxResult getCode(HttpServletResponse response) throws IOException
{
AjaxResult ajax = AjaxResult.success();
boolean captchaOnOff = configService.selectCaptchaOnOff();
ajax.put("captchaOnOff", captchaOnOff);
if (!captchaOnOff)
{
return ajax;
}
// 保存验证码信息
String uuid = IdUtils.simpleUUID();
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
String capStr = null, code = null;
BufferedImage image = null;
// 生成验证码
String captchaType = RuoYiConfig.getCaptchaType();
if ("math".equals(captchaType))
{
String capText = captchaProducerMath.createText();
capStr = capText.substring(0, capText.lastIndexOf("@"));
code = capText.substring(capText.lastIndexOf("@") + 1);
image = captchaProducerMath.createImage(capStr);
}
else if ("char".equals(captchaType))
{
capStr = code = captchaProducer.createText();
image = captchaProducer.createImage(capStr);
}
redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
// 转换流信息写出
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
try
{
ImageIO.write(image, "jpg", os);
}
catch (IOException e)
{
return AjaxResult.error(e.getMessage());
}
ajax.put("uuid", uuid);
ajax.put("img", Base64.encode(os.toByteArray()));
return ajax;
}
}

View File

@ -1,7 +1,5 @@
package com.ruoyi.web.controller.common; package com.ruoyi.web.controller.common;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -10,7 +8,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.config.RuoYiConfig;
@ -27,7 +24,6 @@ import com.ruoyi.framework.config.ServerConfig;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/common")
public class CommonController public class CommonController
{ {
private static final Logger log = LoggerFactory.getLogger(CommonController.class); private static final Logger log = LoggerFactory.getLogger(CommonController.class);
@ -35,15 +31,13 @@ public class CommonController
@Autowired @Autowired
private ServerConfig serverConfig; private ServerConfig serverConfig;
private static final String FILE_DELIMETER = ",";
/** /**
* 通用下载请求 * 通用下载请求
* *
* @param fileName 文件名称 * @param fileName 文件名称
* @param delete 是否删除 * @param delete 是否删除
*/ */
@GetMapping("/download") @GetMapping("common/download")
public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
{ {
try try
@ -70,9 +64,9 @@ public class CommonController
} }
/** /**
* 通用上传请求单个 * 通用上传请求
*/ */
@PostMapping("/upload") @PostMapping("/common/upload")
public AjaxResult uploadFile(MultipartFile file) throws Exception public AjaxResult uploadFile(MultipartFile file) throws Exception
{ {
try try
@ -83,47 +77,8 @@ public class CommonController
String fileName = FileUploadUtils.upload(filePath, file); String fileName = FileUploadUtils.upload(filePath, file);
String url = serverConfig.getUrl() + fileName; String url = serverConfig.getUrl() + fileName;
AjaxResult ajax = AjaxResult.success(); AjaxResult ajax = AjaxResult.success();
ajax.put("url", url);
ajax.put("fileName", fileName); ajax.put("fileName", fileName);
ajax.put("newFileName", FileUtils.getName(fileName)); ajax.put("url", url);
ajax.put("originalFilename", file.getOriginalFilename());
return ajax;
}
catch (Exception e)
{
return AjaxResult.error(e.getMessage());
}
}
/**
* 通用上传请求多个
*/
@PostMapping("/uploads")
public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception
{
try
{
// 上传文件路径
String filePath = RuoYiConfig.getUploadPath();
List<String> urls = new ArrayList<String>();
List<String> fileNames = new ArrayList<String>();
List<String> newFileNames = new ArrayList<String>();
List<String> originalFilenames = new ArrayList<String>();
for (MultipartFile file : files)
{
// 上传并返回新文件名称
String fileName = FileUploadUtils.upload(filePath, file);
String url = serverConfig.getUrl() + fileName;
urls.add(url);
fileNames.add(fileName);
newFileNames.add(FileUtils.getName(fileName));
originalFilenames.add(file.getOriginalFilename());
}
AjaxResult ajax = AjaxResult.success();
ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));
ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
return ajax; return ajax;
} }
catch (Exception e) catch (Exception e)
@ -135,7 +90,7 @@ public class CommonController
/** /**
* 本地资源通用下载 * 本地资源通用下载
*/ */
@GetMapping("/download/resource") @GetMapping("/common/download/resource")
public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response) public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
throws Exception throws Exception
{ {

View File

@ -125,17 +125,16 @@ public class SysDeptController extends BaseController
@PutMapping @PutMapping
public AjaxResult edit(@Validated @RequestBody SysDept dept) public AjaxResult edit(@Validated @RequestBody SysDept dept)
{ {
Long deptId = dept.getDeptId();
deptService.checkDeptDataScope(deptId);
if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept)))
{ {
return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在"); return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
} }
else if (dept.getParentId().equals(deptId)) else if (dept.getParentId().equals(dept.getDeptId()))
{ {
return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己"); return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己");
} }
else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0) else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus())
&& deptService.selectNormalChildrenDeptById(dept.getDeptId()) > 0)
{ {
return AjaxResult.error("该部门包含未停用的子部门!"); return AjaxResult.error("该部门包含未停用的子部门!");
} }
@ -159,7 +158,6 @@ public class SysDeptController extends BaseController
{ {
return AjaxResult.error("部门存在用户,不允许删除"); return AjaxResult.error("部门存在用户,不允许删除");
} }
deptService.checkDeptDataScope(deptId);
return toAjax(deptService.deleteDeptById(deptId)); return toAjax(deptService.deleteDeptById(deptId));
} }
} }

View File

@ -12,11 +12,9 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu; import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody; import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.framework.web.service.SysLoginService; import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService; import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysMenuService; import com.ruoyi.system.service.ISysMenuService;
/** /**
@ -36,9 +34,6 @@ public class SysLoginController
@Autowired @Autowired
private SysPermissionService permissionService; private SysPermissionService permissionService;
@Autowired
private TokenService tokenService;
/** /**
* 登录方法 * 登录方法
* *
@ -50,7 +45,8 @@ public class SysLoginController
{ {
AjaxResult ajax = AjaxResult.success(); AjaxResult ajax = AjaxResult.success();
// 生成令牌 // 生成令牌
String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode()); String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
loginBody.getUuid());
ajax.put(Constants.TOKEN, token); ajax.put(Constants.TOKEN, token);
return ajax; return ajax;
} }
@ -63,8 +59,7 @@ public class SysLoginController
@GetMapping("getInfo") @GetMapping("getInfo")
public AjaxResult getInfo() public AjaxResult getInfo()
{ {
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); SysUser user = SecurityUtils.getLoginUser().getUser();
SysUser user = loginUser.getUser();
// 角色集合 // 角色集合
Set<String> roles = permissionService.getRolePermission(user); Set<String> roles = permissionService.getRolePermission(user);
// 权限集合 // 权限集合
@ -84,10 +79,8 @@ public class SysLoginController
@GetMapping("getRouters") @GetMapping("getRouters")
public AjaxResult getRouters() public AjaxResult getRouters()
{ {
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); Long userId = SecurityUtils.getUserId();
// 用户信息 List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
SysUser user = loginUser.getUser();
List<SysMenu> menus = menuService.selectMenuTreeByUserId(user.getUserId());
return AjaxResult.success(menuService.buildMenus(menus)); return AjaxResult.success(menuService.buildMenus(menus));
} }
} }

View File

@ -28,10 +28,10 @@ public class SysRegisterController extends BaseController
@PostMapping("/register") @PostMapping("/register")
public AjaxResult register(@RequestBody RegisterBody user) public AjaxResult register(@RequestBody RegisterBody user)
{ {
// if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser"))))
// { {
// return error("当前系统没有开启注册功能!"); return error("当前系统没有开启注册功能!");
// } }
String msg = registerService.register(user); String msg = registerService.register(user);
return StringUtils.isEmpty(msg) ? success() : error(msg); return StringUtils.isEmpty(msg) ? success() : error(msg);
} }

View File

@ -111,7 +111,6 @@ public class SysRoleController extends BaseController
public AjaxResult edit(@Validated @RequestBody SysRole role) public AjaxResult edit(@Validated @RequestBody SysRole role)
{ {
roleService.checkRoleAllowed(role); roleService.checkRoleAllowed(role);
roleService.checkRoleDataScope(role.getRoleId());
if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role)))
{ {
return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在"); return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
@ -146,7 +145,6 @@ public class SysRoleController extends BaseController
public AjaxResult dataScope(@RequestBody SysRole role) public AjaxResult dataScope(@RequestBody SysRole role)
{ {
roleService.checkRoleAllowed(role); roleService.checkRoleAllowed(role);
roleService.checkRoleDataScope(role.getRoleId());
return toAjax(roleService.authDataScope(role)); return toAjax(roleService.authDataScope(role));
} }
@ -159,7 +157,6 @@ public class SysRoleController extends BaseController
public AjaxResult changeStatus(@RequestBody SysRole role) public AjaxResult changeStatus(@RequestBody SysRole role)
{ {
roleService.checkRoleAllowed(role); roleService.checkRoleAllowed(role);
roleService.checkRoleDataScope(role.getRoleId());
role.setUpdateBy(getUsername()); role.setUpdateBy(getUsername());
return toAjax(roleService.updateRoleStatus(role)); return toAjax(roleService.updateRoleStatus(role));
} }
@ -239,7 +236,6 @@ public class SysRoleController extends BaseController
@PutMapping("/authUser/selectAll") @PutMapping("/authUser/selectAll")
public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds) public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds)
{ {
roleService.checkRoleDataScope(roleId);
return toAjax(roleService.insertAuthUsers(roleId, userIds)); return toAjax(roleService.insertAuthUsers(roleId, userIds));
} }
} }

View File

@ -104,10 +104,9 @@ public class SysUserController extends BaseController
ajax.put("posts", postService.selectPostAll()); ajax.put("posts", postService.selectPostAll());
if (StringUtils.isNotNull(userId)) if (StringUtils.isNotNull(userId))
{ {
SysUser sysUser = userService.selectUserById(userId); ajax.put(AjaxResult.DATA_TAG, userService.selectUserById(userId));
ajax.put(AjaxResult.DATA_TAG, sysUser);
ajax.put("postIds", postService.selectPostListByUserId(userId)); ajax.put("postIds", postService.selectPostListByUserId(userId));
ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList())); ajax.put("roleIds", roleService.selectRoleListByUserId(userId));
} }
return ajax; return ajax;
} }
@ -148,7 +147,6 @@ public class SysUserController extends BaseController
public AjaxResult edit(@Validated @RequestBody SysUser user) public AjaxResult edit(@Validated @RequestBody SysUser user)
{ {
userService.checkUserAllowed(user); userService.checkUserAllowed(user);
userService.checkUserDataScope(user.getUserId());
if (StringUtils.isNotEmpty(user.getPhonenumber()) if (StringUtils.isNotEmpty(user.getPhonenumber())
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
{ {
@ -187,7 +185,6 @@ public class SysUserController extends BaseController
public AjaxResult resetPwd(@RequestBody SysUser user) public AjaxResult resetPwd(@RequestBody SysUser user)
{ {
userService.checkUserAllowed(user); userService.checkUserAllowed(user);
userService.checkUserDataScope(user.getUserId());
user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
user.setUpdateBy(getUsername()); user.setUpdateBy(getUsername());
return toAjax(userService.resetPwd(user)); return toAjax(userService.resetPwd(user));
@ -202,7 +199,6 @@ public class SysUserController extends BaseController
public AjaxResult changeStatus(@RequestBody SysUser user) public AjaxResult changeStatus(@RequestBody SysUser user)
{ {
userService.checkUserAllowed(user); userService.checkUserAllowed(user);
userService.checkUserDataScope(user.getUserId());
user.setUpdateBy(getUsername()); user.setUpdateBy(getUsername());
return toAjax(userService.updateUserStatus(user)); return toAjax(userService.updateUserStatus(user));
} }
@ -230,7 +226,6 @@ public class SysUserController extends BaseController
@PutMapping("/authRole") @PutMapping("/authRole")
public AjaxResult insertAuthRole(Long userId, Long[] roleIds) public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
{ {
userService.checkUserDataScope(userId);
userService.insertUserAuth(userId, roleIds); userService.insertUserAuth(userId, roleIds);
return success(); return success();
} }

View File

@ -1,172 +0,0 @@
package com.ruoyi.web.controller.yada;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.system.domain_yada.*;
import com.ruoyi.system.service_yada.IAorestCoverageService;
import com.ruoyi.system.service_yada.IAustraliaMiddleEastService;
import com.ruoyi.system.service_yada.ThematicMapService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.crypto.Data;
import java.io.InputStream;
import java.security.Guard;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.List;
/**
* 森林覆盖率
*/
@RestController
@RequestMapping(value = "/business-service/api/Aorest", produces = "application/json;charset=UTF-8")
@Api(tags = "森林覆盖率")
public class AorestCoverageController {
@Resource
private IAorestCoverageService service;
@Resource
private ThematicMapService thematicMapService;
/**
* 查询方法
* 需要查询的字段参数
* @return 参数类
*/
@RequestMapping(value = "/selectAorestCoverage",method = {RequestMethod.GET})
@ApiOperation(value = "查询方法",httpMethod = "GET")
public AjaxResult selectAorestCoverage()
{
List<AorestCoverageVO> eastVOSList= service.selectAorestCoverage();
return AjaxResult.success(eastVOSList);
}
/**
* 删除方法
* @param ID id
* @return 状态码
*/
@RequestMapping(value = "/DelAorestCoverage",method = {RequestMethod.DELETE})
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
@ApiOperation(value = "删除方法",httpMethod = "DELETE")
public AjaxResult DelAorestCoverage(@Param("ID") String ID)
{
int NUM = service.DelAorestCoverage(ID);
if (NUM>0)
{
return AjaxResult.success();
}
return AjaxResult.error();
}
/**
* 新增方法
* @param eastVOS 新增实体类
* @return 状态码
*/
@RequestMapping(value = "/IntoAorestCoverage",method = {RequestMethod.POST})
@ApiOperation(value = "新增方法",httpMethod = "POST")
public AjaxResult IntoAorestCoverage(@RequestBody AorestCoverageVO eastVOS)
{
try {
eastVOS.setCreateTime(LocalDateTime.now());
int NUM = service.IntoAorestCoverage(eastVOS);
if (NUM>0)
{
return AjaxResult.success();
}
return AjaxResult.error();
}
catch (Exception E){
E.getMessage();
return AjaxResult.error();
}
}
/**
* 上传文件
* @return 状态码
*/
@RequestMapping(value = "/IntoUpLoad",method = {RequestMethod.POST})
@ApiOperation(value = "上传文件",httpMethod = "POST")
public AjaxResult IntoUpload(@RequestBody MultipartFile file)
{
UploadFile upload=new UploadFile();
ThematicMapDomain domain=new ThematicMapDomain();
UploadFile value= null;
try {
value = uploadFile(file,upload);
} catch (Exception e) {
e.printStackTrace();
}
int NUM = service.IntoUpload(value);
domain.setPictureCode(value.getFileId());
if (NUM>0)
{
return AjaxResult.success();
}
return AjaxResult.error();
}
/**
* 文件查询
* @param response
* @param request 客户端请求
* @return
*/
@RequestMapping(value = "/selectUpload",method = {RequestMethod.GET})
@ApiOperation(value = "文件查询",httpMethod = "GET")
public AjaxResult selectUpload(HttpServletResponse response, HttpServletRequest request,@RequestBody UploadFile upload)
{
List<UploadFile> eastVOSList= service.selectUpload(upload.getFileId(),upload.getFileName());
return AjaxResult.success(eastVOSList);
}
public UploadFile uploadFile(MultipartFile file,UploadFile upload) throws Exception
{
// 上传文件路径
String filePath = RuoYiConfig.getUploadPath();
// 上传并返回新文件名称
String fileName = FileUploadUtils.upload(filePath, file);
upload.setFileId(String.valueOf(System.currentTimeMillis()));
upload.setFileName(file.getOriginalFilename());
upload.setFilePath(fileName);
upload.setFileSize(String.valueOf(file.getSize()));
upload.setCreateTime(LocalDateTime.now());
return upload;
}
@RequestMapping(value = "/Dictionary")
@ApiOperation(value = "字典查询",httpMethod = "POST")
public AjaxResult Dictionary(@RequestBody Dictionary dic)
{
List<Dictionary> diclist=service.selectDic(dic.getCodingType(),dic.getCodingType1(), dic.getCodingType2());
return AjaxResult.success(diclist);
}
}

View File

@ -1,81 +0,0 @@
package com.ruoyi.web.controller.yada;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.service_yada.IAustraliaMiddleEastService;
import com.ruoyi.system.domain_yada.AustraliaMiddleEastVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.List;
/**
* 澳大利亚中东部地区
*/
@RestController
@RequestMapping(value = "/business-service/api/Australia", produces = "application/json;charset=UTF-8")
@Api(tags = "澳大利亚中东部地区")
public class AustraliaMiddleEastController
{
@Resource
private IAustraliaMiddleEastService australiaMiddleEastService;
/**
* 查询方法
* @return 实体类
*/
@ApiOperation(value = "查询方法",httpMethod = "GET")
@RequestMapping(value = "/SelectAustralia",method = {RequestMethod.GET})
public AjaxResult SelectAustralia(@RequestBody AustraliaMiddleEastVO eastVO )
{
List<AustraliaMiddleEastVO> eastVOSList= australiaMiddleEastService.selectAustralia(eastVO.getYearMonth(),eastVO.getMonth());
return AjaxResult.success(eastVOSList);
}
/**
* 删除方法
* @param ID id
* @return 状态码
*/
@RequestMapping(value = "/DelAustralia",method = {RequestMethod.DELETE})
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
@ApiOperation(value = "删除方法",httpMethod = "DELETE")
public AjaxResult DelAustralia(@Param("ID") String ID)
{
int NUM = australiaMiddleEastService.DelAustralia(ID);
if (NUM>0)
{
return AjaxResult.success();
}
return AjaxResult.error();
}
/**
* 新增方法
* @param eastVOS 新增实体类
* @return 状态码
*/
@RequestMapping(value = "/IntoAustralia",method = {RequestMethod.POST})
@ApiOperation(value = "新增方法",httpMethod = "POST")
public AjaxResult IntoAustralia(@RequestBody AustraliaMiddleEastVO eastVOS)
{
eastVOS.setCreateTime(LocalDateTime.now());
int NUM = australiaMiddleEastService.IntoAustralia(eastVOS);
if (NUM>0)
{
return AjaxResult.success();
}
return AjaxResult.error();
}
}

View File

@ -1,85 +0,0 @@
package com.ruoyi.web.controller.yada;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.domain_yada.AustraliaMiddleEastVO;
import com.ruoyi.system.domain_yada.GlobalTypeVO;
import com.ruoyi.system.service_yada.IAustraliaMiddleEastService;
import com.ruoyi.system.service_yada.IGlobalTypeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.List;
/**
*全球各类型占比
*/
@RestController
@RequestMapping("/monitor/clobal")
@Api(tags = "全球各类型占比")
public class GlobalTypeController {
@Resource
private IGlobalTypeService typeService;
/**
* 查询方法
* @param response 响应头
* @param request 客户端请求
* @return 参数类
*/
@RequestMapping(value = "/selectGlobalType",method = {RequestMethod.POST})
@ApiOperation(value = "查询方法",httpMethod = "POST")
public AjaxResult selectGlobalType(HttpServletResponse response, HttpServletRequest request,@RequestBody GlobalTypeVO TypeVO)
{
List<GlobalTypeVO> eastVOSList= typeService.selectGlobalType(TypeVO.getTypeName(),TypeVO.getParticularYear());
return AjaxResult.success(eastVOSList);
}
/**
* 删除方法
* @param ID id
* @return 状态码
*/
@RequestMapping(value = "/DelGlobalType",method = {RequestMethod.DELETE})
@ApiOperation(value = "删除方法",httpMethod = "DELETE")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
public AjaxResult DelGlobalType(@Param("ID") String ID)
{
int NUM = typeService.DelGlobalType(ID);
if (NUM>0)
{
return AjaxResult.success();
}
return AjaxResult.error();
}
/**
* 新增方法
* @param eastVOS 新增实体类
* @return 状态码
*/
@ApiOperation(value = "新增方法",httpMethod = "POST")
@RequestMapping(value = "/IntoGlobalType",method = {RequestMethod.POST})
public AjaxResult IntoGlobalType(@RequestBody GlobalTypeVO eastVOS)
{
eastVOS.setCreateTime(LocalDateTime.now());
int NUM = typeService.IntoGlobalType(eastVOS);
if (NUM>0)
{
return AjaxResult.success();
}
return AjaxResult.error();
}
}

View File

@ -1,83 +0,0 @@
package com.ruoyi.web.controller.yada;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.domain_yada.AustraliaMiddleEastVO;
import com.ruoyi.system.domain_yada.OceanTemperatureVO;
import com.ruoyi.system.service_yada.IAustraliaMiddleEastService;
import com.ruoyi.system.service_yada.IOceanTemperatureService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.List;
/**
* 海洋表面温度监测
*/
@Api(tags = "海洋表面温度监测")
@RestController
@RequestMapping(value = "/business-service/api/Ocean", produces = "application/json;charset=UTF-8")
public class OceanTemperatureController {
@Resource
private IOceanTemperatureService temperatureService;
/**
* 查询方法
* @return 参数类
*/
@RequestMapping(value = "/selectOcean",method = {RequestMethod.GET})
@ApiOperation(value = "查询方法",httpMethod = "GET")
public AjaxResult selectOcean(@RequestBody OceanTemperatureVO temperatureVO)
{
List<OceanTemperatureVO> eastVOSList= temperatureService.selectOcean(temperatureVO.getStartDate());
return AjaxResult.success(eastVOSList);
}
/**
* 删除方法
* @param ID id
* @return 状态码
*/
@RequestMapping(value = "/DelOcean",method = {RequestMethod.DELETE})
@ApiOperation(value = "删除方法",httpMethod = "DELETE")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
public AjaxResult DelOcean(@Param("ID") String ID)
{
int NUM = temperatureService.DelOcean(ID);
if (NUM>0)
{
return AjaxResult.success();
}
return AjaxResult.error();
}
/**
* 新增方法
* @param eastVOS 新增实体类
* @return 状态码
*/
@ApiOperation(value = "新增方法",httpMethod = "POST")
@RequestMapping(value = "/IntoAustralia",method = {RequestMethod.POST})
public AjaxResult IntoOcean(@RequestBody OceanTemperatureVO eastVOS)
{
eastVOS.setCreateTime(LocalDateTime.now());
int NUM = temperatureService.IntoOcean(eastVOS);
if (NUM>0)
{
return AjaxResult.success();
}
return AjaxResult.error();
}
}

View File

@ -1,81 +0,0 @@
package com.ruoyi.web.controller.yada;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.service_yada.IRegionVGIService;
import com.ruoyi.system.domain_yada.RegionVGIVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.List;
/**
* 各区域VGI
*/
@Api(tags = "各区域VGI")
@RestController
@RequestMapping(value = "/business-service/api/orderMng", produces = "application/json;charset=UTF-8")
public class RegionVGIController
{
@Resource
private IRegionVGIService regionVGIService;
/**
* 查询方法
* @return 参数类
*/
@RequestMapping(value = "/SelectRegion",method = {RequestMethod.GET})
@ApiOperation(value = "查询方法",httpMethod = "GET")
public AjaxResult SelectRegion()
{
List<RegionVGIVO> vgivost= regionVGIService.selectRegion();
return AjaxResult.success(vgivost);
}
/**
* 删除方法
* @param ID id
* @return 状态码
*/
@RequestMapping(value = "/DelRegion",method = {RequestMethod.DELETE})
@ApiOperation(value = "删除方法",httpMethod = "DELETE")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
public AjaxResult DelRegion(@Param("ID") String ID)
{
int NUM = regionVGIService.DelRegion(ID);
if (NUM>0)
{
return AjaxResult.success();
}
return AjaxResult.error();
}
/**
* 新增方法
* @param vgivo 新增实体类
* @return 状态码
*/
@ApiOperation(value = "新增方法",httpMethod = "POST")
@RequestMapping(value = "/IntoRegion",method = {RequestMethod.POST})
public AjaxResult IntoRegion(@RequestBody RegionVGIVO vgivo)
{
vgivo.setCreatedTime(LocalDateTime.now());
int NUM = regionVGIService.IntoRegion(vgivo);
if (NUM>0)
{
return AjaxResult.success();
}
return AjaxResult.error();
}
}

View File

@ -1,76 +0,0 @@
package com.ruoyi.web.controller.yada;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.domain_yada.AustraliaMiddleEastVO;
import com.ruoyi.system.domain_yada.RegionVGIVO;
import com.ruoyi.system.domain_yada.RegionalSystemVO;
import com.ruoyi.system.service_yada.IAustraliaMiddleEastService;
import com.ruoyi.system.service_yada.IRegionalSystemService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
/**
* 区域生态系统
*/
@Api(tags = "区域生态系统")
@RestController
@RequestMapping(value = "/business-service/api/Regional", produces = "application/json;charset=UTF-8")
public class RegionalSystemController {
@Resource
private IRegionalSystemService systemService;
/**
* 查询方法
* @return 参数类
*/
@RequestMapping(value = "/selectRegional",method = {RequestMethod.GET})
@ApiOperation(value = "查询方法",httpMethod = "GET")
public AjaxResult selectRegional(@RequestParam("region") String region)
{
List<RegionalSystemVO> eastVOSList= systemService.selectRegional(region);
return AjaxResult.success(eastVOSList);
}
/**
* 删除方法
* @param ID id
* @return 状态码
*/
@RequestMapping(value = "/DelRegional",method = {RequestMethod.DELETE})
@ApiOperation(value = "删除方法",httpMethod = "DELETE")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
public AjaxResult DelRegional(@RequestParam("ID") String ID)
{
int NUM = systemService.DelRegional(ID);
if (NUM>0)
{
return AjaxResult.success();
}
return AjaxResult.error();
}
/**
* 新增方法
* @param eastVOS 新增实体类
* @return 状态码
*/
@ApiOperation(value = "新增方法",httpMethod = "POST")
@RequestMapping(value = "/IntoRegional",method = {RequestMethod.POST})
public AjaxResult IntoRegional(@RequestBody RegionalSystemVO eastVOS)
{
eastVOS.setCreateTime(LocalDateTime.now());
int NUM = systemService.IntoRegional(eastVOS);
if (NUM>0)
{
return AjaxResult.success();
}
return AjaxResult.error();
}
}

View File

@ -1,330 +0,0 @@
package com.ruoyi.web.controller.yada;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.file.WeatherUtils;
import com.ruoyi.system.domain_yada.*;
import com.ruoyi.system.service_yada.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jdk.jfr.Frequency;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.spring.web.json.Json;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.http.HttpRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping(value = "/Special")
@Api(tags = "模板导入")
public class SpecialController {
@Resource
private IRegionVGIService regionVGIService;
@Resource
private IAustraliaMiddleEastService australiaMiddleEastService;
@Resource
private IAorestCoverageService service;
@Resource
private IVegetationCoverageService coverageService;
@Resource
private IRegionalSystemService systemService;
/**
*/
@RequestMapping(value = "/helpSaveExcel")
private AjaxResult helpSaveExcel(@RequestBody MultipartFile file) {
List<RegionVGIVO> value = saveExcel(file);
return IntoRegion(value);
}
@RequestMapping(value = "/helpWeatherClass",method = {RequestMethod.GET})
public AjaxResult helpWeatherClass(String city,String type)
{
String url="https://restapi.amap.com/v3/weather/weatherInfo";
Map<String,String> map=new HashMap<>();
map.put("key","37087f0a3007dc67d37859553cd02d33");
map.put("city",city);
if (type!=null){ map.put("extensions",type);}
map.put("output","json");
String value= WeatherUtils.httpRequest(url,map);
WeatherUtilsVO vo = JSON.parseObject(value,WeatherUtilsVO.class);
// String value2=vo.getForecasts().substring(1,vo.getForecasts().length()-1);
// System.out.println(value2);
// vo.setForecast(JSON.parseObject(value2,ForecastVo.class));
// JSONObject userJson=JSONObject.parseObject(value);
// WeatherUtilsVO utilsValue= JSON.toJavaObject(userJson,WeatherUtilsVO.class);
return AjaxResult.success(vo);
} /**
* 森林覆盖率模板导入
*/
@RequestMapping(value = "/helpExcelAorest")
private AjaxResult helpExcelAorest(@RequestBody MultipartFile file) {
List<AorestCoverageVO> value = saveExcelAorest(file);
return IntoAorestCoverage(value);
}
/**
*平均植被覆盖度和净初级生产力
*/
@RequestMapping(value = "/helpExcelnpp")
private AjaxResult helpExcelnpp(@RequestBody MultipartFile file) {
List<VegetationCoverageVO> value = saveExcelnpp(file);
return IntoVegetation(value);
}
/**
* 澳大利亚中部地区模板导入
*/
@RequestMapping(value = "/helpExcelAus")
private AjaxResult helpExcelAus(@RequestBody MultipartFile file) {
List<AustraliaMiddleEastVO> value = saveExcelAus(file);
return IntoAustralia(value);
}
/**
* 区域生态系统类型转移
*/
@RequestMapping(value = "/helpExcelRegion")
private AjaxResult helpExcelRegion(@RequestBody MultipartFile file) {
List<RegionalSystemVO> value = saveExcelRegion(file);
return IntoRegional(value);
}
public AjaxResult IntoRegional(List<RegionalSystemVO> eastVOS)
{
try {
for (int i = 0; i < eastVOS.size(); i++) {
eastVOS.get(i).setCreateTime(LocalDateTime.now());
systemService.IntoRegional(eastVOS.get(i));
}
return AjaxResult.success();
}
catch (Exception E){
E.getMessage();
return AjaxResult.error(E.getMessage());
}
}
public AjaxResult IntoAustralia(List<AustraliaMiddleEastVO> eastVOS) {
for (int i = 0; i < eastVOS.size(); i++) {
eastVOS.get(i).setCreateTime(LocalDateTime.now());
australiaMiddleEastService.IntoAustralia(eastVOS.get(i));
}
return AjaxResult.success();
}
public AjaxResult IntoRegion(List<RegionVGIVO> vgivo) {
for (int i = 0; i < vgivo.size(); i++) {
vgivo.get(i).setCreatedTime(LocalDateTime.now());
regionVGIService.IntoRegion(vgivo.get(i));
}
return AjaxResult.success();
}
public AjaxResult IntoAorestCoverage(List<AorestCoverageVO> eastVOS)
{
try {
for (int i = 0; i < eastVOS.size(); i++) {
eastVOS.get(i).setCreateTime(LocalDateTime.now());
service.IntoAorestCoverage(eastVOS.get(i));
}
return AjaxResult.success();
}
catch (Exception E){
E.getMessage();
return AjaxResult.error(E.getMessage());
}
}
public AjaxResult IntoVegetation(List<VegetationCoverageVO> eastVOS)
{
try {
for (int i = 0; i < eastVOS.size(); i++) {
eastVOS.get(i).setCreateTime(LocalDateTime.now());
coverageService.IntoVegetation(eastVOS.get(i));
}
return AjaxResult.success();
}
catch (Exception E){
E.getMessage();
return AjaxResult.error(E.getMessage());
}
}
private List<RegionVGIVO> saveExcel(MultipartFile file) {
try {
List<RegionVGIVO> Value = new ArrayList<>();
InputStream inputStream = file.getInputStream();
Workbook book;
Sheet sheet;
book = new XSSFWorkbook(inputStream);
sheet = book.getSheetAt(0);
for (int i = 1; i < sheet.getLastRowNum() + 1; i++) {
RegionVGIVO value = new RegionVGIVO();
Row row = sheet.getRow(i);
value.setCreatedTime(LocalDateTime.now());
value.setRegion(row.getCell(0).toString());
value.setRegionEn(row.getCell(1).toString());
value.setForest(Double.parseDouble(row.getCell(2).toString()));
value.setGrassland(Double.parseDouble(row.getCell(3).toString()));
value.setParticularYear(row.getCell(4).toString());
Value.add(value);
}
return Value;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private List<AustraliaMiddleEastVO> saveExcelAus(MultipartFile file) {
try {
List<AustraliaMiddleEastVO> Value = new ArrayList<>();
InputStream inputStream = file.getInputStream();
Workbook book;
Sheet sheet;
book = new XSSFWorkbook(inputStream);
sheet = book.getSheetAt(0);
for (int i = 1; i < sheet.getLastRowNum() + 1; i++) {
AustraliaMiddleEastVO value = new AustraliaMiddleEastVO();
Row row = sheet.getRow(i);
value.setYearMonth(row.getCell(0).toString());
value.setMonth(row.getCell(1).toString());
value.setSstAnomalyIndex(Double.parseDouble(row.getCell(2).toString()));
value.setTemperatureAnomolies(Double.parseDouble(row.getCell(3).toString()));
value.setPrecipitationAnomolies(Double.parseDouble(row.getCell(4).toString()));
value.setVaiAnomolies(Double.parseDouble(row.getCell(5).toString()));
Value.add(value);
}
return Value;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private List<AorestCoverageVO> saveExcelAorest(MultipartFile file) {
try {
List<AorestCoverageVO> Value = new ArrayList<>();
InputStream inputStream = file.getInputStream();
Workbook book;
Sheet sheet;
book = new XSSFWorkbook(inputStream);
sheet = book.getSheetAt(0);
for (int i = 1; i < sheet.getLastRowNum() + 1; i++) {
AorestCoverageVO value = new AorestCoverageVO();
Row row = sheet.getRow(i);
value.setRegion(row.getCell(0).toString());
value.setRegionEn(row.getCell(1).toString());
value.setProtectedLands(Double.parseDouble(row.getCell(2).toString()));
value.setNonProtectedLands(Double.parseDouble(row.getCell(3).toString()));
value.setMountain(Double.parseDouble(row.getCell(4).toString()));
value.setNonMountain(Double.parseDouble(row.getCell(5).toString()));
value.setCreateTime(LocalDateTime.now());
Value.add(value);
}
return Value;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private List<VegetationCoverageVO> saveExcelnpp(MultipartFile file) {
try {
List<VegetationCoverageVO> Value = new ArrayList<>();
InputStream inputStream = file.getInputStream();
Workbook book;
Sheet sheet;
book = new XSSFWorkbook(inputStream);
sheet = book.getSheetAt(0);
for (int i = 1; i < sheet.getLastRowNum() + 1; i++) {
VegetationCoverageVO value = new VegetationCoverageVO();
Row row = sheet.getRow(i);
value.setRegion(row.getCell(0).toString());
value.setRegionEn(row.getCell(1).toString());
value.setProtectedLands(Double.parseDouble(row.getCell(4).toString()));
value.setNonProtectedLands(Double.parseDouble(row.getCell(5).toString()));
value.setMountain(Double.parseDouble(row.getCell(2).toString()));
value.setNonMountain(Double.parseDouble(row.getCell(3).toString()));
value.setCreateTime(LocalDateTime.now());
Value.add(value);
}
return Value;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private List<RegionalSystemVO> saveExcelRegion(MultipartFile file) {
try {
List<RegionalSystemVO> Value = new ArrayList<>();
InputStream inputStream = file.getInputStream();
Workbook book;
Sheet sheet;
book = new XSSFWorkbook(inputStream);
sheet = book.getSheetAt(0);
for (int i = 1; i < sheet.getLastRowNum() + 1; i++) {
RegionalSystemVO value = new RegionalSystemVO();
Row row = sheet.getRow(i);
value.setRegion(row.getCell(0).toString());
value.setRegionEn(row.getCell(1).toString());
value.setTypeConversion(row.getCell(2).toString());
value.setTypeconversionEn(row.getCell(3).toString());
value.setProportionOfChangedAreas(Double.parseDouble(row.getCell(4).toString()));
value.setCreateTime(LocalDateTime.now());
Value.add(value);
}
return Value;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}

View File

@ -1,92 +0,0 @@
package com.ruoyi.web.controller.yada;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.system.domain_yada.ThematicMapDomain;
import com.ruoyi.system.service_yada.ThematicMapService;
import io.swagger.annotations.*;
import org.apache.ibatis.annotations.Param;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.List;
/**
* 专题图模块
* @author taco chen
*/
@RestController
@RequestMapping(value = "/thematic-map")
@Api(tags = "专题图模块")
public class ThematicMapController {
@Resource
private ThematicMapService thematicMapService;
/**
* 查询方法
* @param response 响应头
* @return 参数类
*/
@ApiOperation("获取所有专题图")
@ApiImplicitParams({})
@ApiResponses({
@ApiResponse(code =200,message = "请求成功"),
@ApiResponse(code =401,message = "没有认证"),
@ApiResponse(code =403,message = "权限不足"),
@ApiResponse(code =404,message = "未找到")
})
@RequestMapping(value = "/get/all",method = {RequestMethod.POST})
public AjaxResult selectAllThematicMap(HttpServletResponse response,@RequestBody ThematicMapDomain thematicMapDomain)
{
List<ThematicMapDomain> res= thematicMapService.selectAll(thematicMapDomain.getPictureType(),
thematicMapDomain.getPictureTypeOne(),thematicMapDomain.getPictureTypeTwo());
return AjaxResult.success(res);
}
/**
* 删除方法
* @param id id
* @return 状态码
*/
@RequestMapping(value = "/delete",method = {RequestMethod.DELETE})
@ApiOperation(value = "删除方法",httpMethod = "DELETE")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "long", paramType = "path", dataTypeClass = long.class)
public AjaxResult deleteThematicMap(@Param("id") Long id)
{
int num = thematicMapService.deleteById(id);
if (num>0) {
return AjaxResult.success();
}
return AjaxResult.error();
}
/**
* 新增方法
* @param thematicMapDomain 新增实体类
* @return 状态码
*/
@ApiOperation(value = "新增方法",httpMethod = "POST")
@RequestMapping(value = "/add",method = {RequestMethod.POST})
public AjaxResult saveThematicMap(@RequestBody ThematicMapDomain thematicMapDomain)
{
thematicMapDomain.setCreatedTime(LocalDateTime.now());
int num = thematicMapService.save(thematicMapDomain);
if (num>0) {
return AjaxResult.success();
}
return AjaxResult.error();
}
}

View File

@ -1,84 +0,0 @@
package com.ruoyi.web.controller.yada;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.domain_yada.AustraliaMiddleEastVO;
import com.ruoyi.system.domain_yada.UrbanVO;
import com.ruoyi.system.service_yada.IAustraliaMiddleEastService;
import com.ruoyi.system.service_yada.IUrbanService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.List;
/**
* 中国城市监测
*/
@Api(tags = "中国城市监测")
@RestController
@RequestMapping(value = "/business-service/api/Urban", produces = "application/json;charset=UTF-8")
public class UrbanController {
@Resource
private IUrbanService urbanService;
/**
* 查询方法
* @param response 响应头
* @param request 客户端请求
* @return 参数类
*/
@RequestMapping(value = "/selectUrban",method = {RequestMethod.GET})
@ApiOperation(value = "查询方法",httpMethod = "GET")
public AjaxResult selectUrban(HttpServletResponse response, HttpServletRequest request,@RequestBody UrbanVO urbanVO)
{
List<UrbanVO> eastVOSList= urbanService.selectUrban(urbanVO.getName(),urbanVO.getParticularYear());
return AjaxResult.success(eastVOSList);
}
/**
* 删除方法
* @param ID id
* @return 状态码
*/
@RequestMapping(value = "/DelUrban",method = {RequestMethod.DELETE})
@ApiOperation(value = "删除方法",httpMethod = "DELETE")
public AjaxResult DelUrban(@Param("ID") String ID)
{
int NUM = urbanService.DelUrban(ID);
if (NUM>0)
{
return AjaxResult.success();
}
return AjaxResult.error();
}
/**
* 新增方法
* @param eastVOS 新增实体类
* @return 状态码
*/
@ApiOperation(value = "新增方法",httpMethod = "POST")
@RequestMapping(value = "/IntoUrban",method = {RequestMethod.POST})
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "long", paramType = "path", dataTypeClass = long.class)
public AjaxResult IntoUrban(@RequestBody UrbanVO eastVOS)
{
eastVOS.setCreateTime(LocalDateTime.now());
int NUM = urbanService.IntoUrban(eastVOS);
if (NUM>0)
{
return AjaxResult.success();
}
return AjaxResult.error();
}
}

View File

@ -1,82 +0,0 @@
package com.ruoyi.web.controller.yada;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.domain_yada.AustraliaMiddleEastVO;
import com.ruoyi.system.domain_yada.VegetationCoverageVO;
import com.ruoyi.system.service_yada.IAustraliaMiddleEastService;
import com.ruoyi.system.service_yada.IVegetationCoverageService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.List;
/**
* 平均植被覆盖度和净初级生产力
*/
@Api(tags = "平均植被覆盖度和净初级生产力")
@RestController
@RequestMapping(value = "/business-service/api/Vegetation", produces = "application/json;charset=UTF-8")
public class VegetationCoverageController {
@Resource
private IVegetationCoverageService coverageService;
/**
* 查询方法
* @return 参数类
*/
@RequestMapping(value = "/selectVegetation",method = {RequestMethod.GET})
@ApiOperation(value = "查询方法",httpMethod = "GET")
public AjaxResult selectVegetation()
{
List<VegetationCoverageVO> eastVOSList= coverageService.selectVegetation();
return AjaxResult.success(eastVOSList);
}
/**
* 删除方法
* @param ID id
* @return 状态码
*/
@RequestMapping(value = "/DelVegetation",method = {RequestMethod.DELETE})
@ApiOperation(value = "删除方法",httpMethod = "DELETE")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "long", paramType = "path", dataTypeClass = long.class)
public AjaxResult DelVegetation(@Param("ID") String ID)
{
int NUM = coverageService.DelVegetation(ID);
if (NUM>0)
{
return AjaxResult.success();
}
return AjaxResult.error();
}
/**
* 新增方法
* @param eastVOS 新增实体类
* @return 状态码
*/
@ApiOperation(value = "新增方法",httpMethod = "POST")
@RequestMapping(value = "/IntoVegetation",method = {RequestMethod.POST})
public AjaxResult IntoVegetation(@RequestBody VegetationCoverageVO eastVOS)
{
eastVOS.setCreateTime(LocalDateTime.now());
int NUM = coverageService.IntoVegetation(eastVOS);
if (NUM>0)
{
return AjaxResult.success();
}
return AjaxResult.error();
}
}

View File

@ -1 +0,0 @@
com.ruoyi.framework.web.service.CaptchaRedisService

View File

@ -2,17 +2,13 @@
spring: spring:
datasource: datasource:
type: com.alibaba.druid.pool.DruidDataSource type: com.alibaba.druid.pool.DruidDataSource
# driverClassName: com.mysql.cj.jdbc.Driver driverClassName: com.mysql.cj.jdbc.Driver
driver-class-name: org.postgresql.Driver
druid: druid:
# 主库数据源
master: master:
#url: jdbc:postgresql://47.243.79.66:5432/yada?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
#url: jdbc:postgresql://192.168.2.9:5432/yada?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai username: root
# username: postgres password: password
# password: postgres
url: jdbc:postgresql://118.195.242.28:5432/yada?AllowPublicKeyRetrieval=True&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: gty
password: 308525
# 从库数据源 # 从库数据源
slave: slave:
# 从数据源开关/默认关闭 # 从数据源开关/默认关闭
@ -34,9 +30,8 @@ spring:
minEvictableIdleTimeMillis: 300000 minEvictableIdleTimeMillis: 300000
# 配置一个连接在池中最大生存的时间,单位是毫秒 # 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000 maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效select * from pg_stat_activity # 配置检测连接是否有效
# validationQuery: SELECT 1 FROM DUAL validationQuery: SELECT 1 FROM DUAL
validationQuery: SELECT version()
testWhileIdle: true testWhileIdle: true
testOnBorrow: false testOnBorrow: false
testOnReturn: false testOnReturn: false

View File

@ -3,13 +3,13 @@ ruoyi:
# 名称 # 名称
name: RuoYi name: RuoYi
# 版本 # 版本
version: 3.4.0 version: 3.8.0
# 版权年份 # 版权年份
copyrightYear: 2021 copyrightYear: 2021
# 实例演示开关 # 实例演示开关
demoEnabled: true demoEnabled: true
# 文件路径 示例( Windows配置D:/ruoyi/uploadPathLinux配置 /home/ruoyi/uploadPath # 文件路径 示例( Windows配置D:/ruoyi/uploadPathLinux配置 /home/ruoyi/uploadPath
profile: /home/gty/ruoyi/uploadPath profile: D:/ruoyi/uploadPath
# 获取ip地址开关 # 获取ip地址开关
addressEnabled: false addressEnabled: false
# 验证码类型 math 数组计算 char 字符验证 # 验证码类型 math 数组计算 char 字符验证
@ -19,7 +19,6 @@ ruoyi:
server: server:
# 服务器的HTTP端口默认为8080 # 服务器的HTTP端口默认为8080
port: 8080 port: 8080
#port: 6061
servlet: servlet:
# 应用的访问路径 # 应用的访问路径
context-path: / context-path: /
@ -66,7 +65,7 @@ spring:
# 数据库索引 # 数据库索引
database: 0 database: 0
# 密码 # 密码
password: '*&jkjusWETO(^ses%i' password:
# 连接超时时间 # 连接超时时间
timeout: 10s timeout: 10s
lettuce: lettuce:
@ -87,7 +86,7 @@ token:
# 令牌密钥 # 令牌密钥
secret: abcdefghijklmnopqrstuvwxyz secret: abcdefghijklmnopqrstuvwxyz
# 令牌有效期默认30分钟 # 令牌有效期默认30分钟
expireTime: 300 expireTime: 30
# MyBatis配置 # MyBatis配置
mybatis: mybatis:
@ -101,7 +100,6 @@ mybatis:
# PageHelper分页插件 # PageHelper分页插件
pagehelper: pagehelper:
helperDialect: mysql helperDialect: mysql
reasonable: true
supportMethodsArguments: true supportMethodsArguments: true
params: count=countSql params: count=countSql
@ -112,27 +110,11 @@ swagger:
# 请求前缀 # 请求前缀
pathMapping: /dev-api pathMapping: /dev-api
# 滑块验证码
aj:
captcha:
cache-type: redis
# blockPuzzle 滑块 clickWord 文字点选 default默认两者都实例化
type: blockPuzzle
# 右下角显示字
water-mark: ruoyi.vip
# 校验滑动拼图允许误差偏移量(默认5像素)
slip-offset: 5
# aes加密坐标开启或者禁用(true|false)
aes-status: true
# 滑动干扰项(0/1/2)
interference-options: 2
# 防止XSS攻击 # 防止XSS攻击
xss: xss:
# 过滤开关 # 过滤开关
enabled: true enabled: true
# 排除链接(多个用逗号分隔) # 排除链接(多个用逗号分隔)
excludes: /system/notice/* excludes: /system/notice
# 匹配链接 # 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/* urlPatterns: /system/*,/monitor/*,/tool/*

View File

@ -1,6 +1,24 @@
_ Application Version: ${ruoyi.version}
( ) Spring Boot Version: ${spring-boot.version}
| |/') _ __ ___ ////////////////////////////////////////////////////////////////////
(`\/')| , < ( '__)/',__) // _ooOoo_ //
> < | |\`\ | | \__, \ // o8888888o //
(_/\_)(_) (_)(_) (____/ // 88" . "88 //
// (| ^_^ |) //
// O\ = /O //
// ____/`---'\____ //
// .' \\| |// `. //
// / \\||| : |||// \ //
// / _||||| -:- |||||- \ //
// | | \\\ - /// | | //
// | \_| ''\---/'' | | //
// \ .-\__ `-` ___/-. / //
// ___`. .' /--.--\ `. . ___ //
// ."" '< `.___\_<|>_/___.' >'"". //
// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
// \ \ `-. \_ __\ /__ _/ .-` / / //
// ========`-.____`-.___\_____/___.-`____.-'======== //
// `=---=' //
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
// 佛祖保佑 永不宕机 永无BUG //
////////////////////////////////////////////////////////////////////

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.8.2</version> <version>3.8.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,8 +5,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.math.BigDecimal; import java.math.BigDecimal;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import com.ruoyi.common.utils.poi.ExcelHandlerAdapter; import com.ruoyi.common.utils.poi.ExcelHandlerAdapter;
/** /**
@ -58,6 +56,11 @@ public @interface Excel
*/ */
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN; public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
/**
* 导出类型0数字 1字符串
*/
public ColumnType cellType() default ColumnType.STRING;
/** /**
* 导出时在excel中每个列的高度 单位为字符 * 导出时在excel中每个列的高度 单位为字符
*/ */
@ -104,19 +107,9 @@ public @interface Excel
public boolean isStatistics() default false; public boolean isStatistics() default false;
/** /**
* 导出类型0数字 1字符串 * 导出字段对齐方式0默认1靠左2居中3靠右
*/ */
public ColumnType cellType() default ColumnType.STRING; public Align align() default Align.AUTO;
/**
* 导出字体颜色
*/
public IndexedColors color() default IndexedColors.BLACK;
/**
* 导出字段对齐方式
*/
public HorizontalAlignment align() default HorizontalAlignment.CENTER;
/** /**
* 自定义数据处理器 * 自定义数据处理器

View File

@ -142,26 +142,16 @@ public class Constants
/** /**
* RMI 远程方法调用 * RMI 远程方法调用
*/ */
public static final String LOOKUP_RMI = "rmi:"; public static final String LOOKUP_RMI = "rmi://";
/** /**
* LDAP 远程方法调用 * LDAP 远程方法调用
*/ */
public static final String LOOKUP_LDAP = "ldap:"; public static final String LOOKUP_LDAP = "ldap://";
/**
* LDAPS 远程方法调用
*/
public static final String LOOKUP_LDAPS = "ldaps:";
/**
* 定时任务白名单配置仅允许访问的包名如其他需要可以自行添加
*/
public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" };
/** /**
* 定时任务违规的字符 * 定时任务违规的字符
*/ */
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml", public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
"org.springframework", "org.apache", "com.ruoyi.common.utils.file" }; "org.springframework.jndi" };
} }

View File

@ -109,9 +109,6 @@ public class GenConstants
/** 模糊查询 */ /** 模糊查询 */
public static final String QUERY_LIKE = "LIKE"; public static final String QUERY_LIKE = "LIKE";
/** 相等查询 */
public static final String QUERY_EQ = "EQ";
/** 需要 */ /** 需要 */
public static final String REQUIRE = "1"; public static final String REQUIRE = "1";
} }

View File

@ -16,7 +16,6 @@ import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.page.TableSupport; import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.sql.SqlUtil; import com.ruoyi.common.utils.sql.SqlUtil;
@ -52,7 +51,15 @@ public class BaseController
*/ */
protected void startPage() protected void startPage()
{ {
PageUtils.startPage(); PageDomain pageDomain = TableSupport.buildPageRequest();
Integer pageNum = pageDomain.getPageNum();
Integer pageSize = pageDomain.getPageSize();
if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize))
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
Boolean reasonable = pageDomain.getReasonable();
PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
}
} }
/** /**
@ -68,14 +75,6 @@ public class BaseController
} }
} }
/**
* 清理分页的线程变量
*/
protected void clearPage()
{
PageUtils.clearPage();
}
/** /**
* 响应请求分页数据 * 响应请求分页数据
*/ */

View File

@ -4,7 +4,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.validation.constraints.Email; import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
@ -32,7 +31,7 @@ public class SysDept extends BaseEntity
private String deptName; private String deptName;
/** 显示顺序 */ /** 显示顺序 */
private Integer orderNum; private String orderNum;
/** 负责人 */ /** 负责人 */
private String leader; private String leader;
@ -97,13 +96,13 @@ public class SysDept extends BaseEntity
this.deptName = deptName; this.deptName = deptName;
} }
@NotNull(message = "显示顺序不能为空") @NotBlank(message = "显示顺序不能为空")
public Integer getOrderNum() public String getOrderNum()
{ {
return orderNum; return orderNum;
} }
public void setOrderNum(Integer orderNum) public void setOrderNum(String orderNum)
{ {
this.orderNum = orderNum; this.orderNum = orderNum;
} }

View File

@ -1,7 +1,6 @@
package com.ruoyi.common.core.domain.entity; package com.ruoyi.common.core.domain.entity;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
@ -58,7 +57,6 @@ public class SysDictType extends BaseEntity
@NotBlank(message = "字典类型不能为空") @NotBlank(message = "字典类型不能为空")
@Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符") @Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符")
@Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)")
public String getDictType() public String getDictType()
{ {
return dictType; return dictType;

View File

@ -3,7 +3,6 @@ package com.ruoyi.common.core.domain.entity;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
@ -31,7 +30,7 @@ public class SysMenu extends BaseEntity
private Long parentId; private Long parentId;
/** 显示顺序 */ /** 显示顺序 */
private Integer orderNum; private String orderNum;
/** 路由地址 */ /** 路由地址 */
private String path; private String path;
@ -108,13 +107,13 @@ public class SysMenu extends BaseEntity
this.parentId = parentId; this.parentId = parentId;
} }
@NotNull(message = "显示顺序不能为空") @NotBlank(message = "显示顺序不能为空")
public Integer getOrderNum() public String getOrderNum()
{ {
return orderNum; return orderNum;
} }
public void setOrderNum(Integer orderNum) public void setOrderNum(String orderNum)
{ {
this.orderNum = orderNum; this.orderNum = orderNum;
} }

View File

@ -2,7 +2,9 @@ package com.ruoyi.common.core.domain.entity;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import javax.validation.constraints.*; import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
@ -12,7 +14,6 @@ import com.ruoyi.common.annotation.Excel.ColumnType;
import com.ruoyi.common.annotation.Excel.Type; import com.ruoyi.common.annotation.Excel.Type;
import com.ruoyi.common.annotation.Excels; import com.ruoyi.common.annotation.Excels;
import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.xss.Xss;
/** /**
* 用户对象 sys_user * 用户对象 sys_user
@ -134,7 +135,6 @@ public class SysUser extends BaseEntity
this.deptId = deptId; this.deptId = deptId;
} }
@Xss(message = "用户昵称不能包含脚本字符")
@Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符") @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符")
public String getNickName() public String getNickName()
{ {
@ -146,7 +146,6 @@ public class SysUser extends BaseEntity
this.nickName = nickName; this.nickName = nickName;
} }
@Xss(message = "用户账号不能包含脚本字符")
@NotBlank(message = "用户账号不能为空") @NotBlank(message = "用户账号不能为空")
@Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符") @Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符")
public String getUserName() public String getUserName()

View File

@ -25,7 +25,7 @@ public class LoginBody
/** /**
* 唯一标识 * 唯一标识
*/ */
private String uuid; private String uuid = "";
public String getUsername() public String getUsername()
{ {

View File

@ -1,6 +1,5 @@
package com.ruoyi.common.core.page; package com.ruoyi.common.core.page;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.ServletUtils;
/** /**
@ -41,8 +40,8 @@ public class TableSupport
public static PageDomain getPageDomain() public static PageDomain getPageDomain()
{ {
PageDomain pageDomain = new PageDomain(); PageDomain pageDomain = new PageDomain();
pageDomain.setPageNum(Convert.toInt(ServletUtils.getParameter(PAGE_NUM), 1)); pageDomain.setPageNum(ServletUtils.getParameterToInt(PAGE_NUM));
pageDomain.setPageSize(Convert.toInt(ServletUtils.getParameter(PAGE_SIZE), 10)); pageDomain.setPageSize(ServletUtils.getParameterToInt(PAGE_SIZE));
pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN)); pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN));
pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC)); pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC));
pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE)); pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE));

View File

@ -213,12 +213,12 @@ public class RedisCache
* 删除Hash中的数据 * 删除Hash中的数据
* *
* @param key * @param key
* @param hKey * @param mapkey
*/ */
public void delCacheMapValue(final String key, final String hKey) public void delCacheMapValue(final String key, final String hkey)
{ {
HashOperations hashOperations = redisTemplate.opsForHash(); HashOperations hashOperations = redisTemplate.opsForHash();
hashOperations.delete(key, hKey); hashOperations.delete(key, hkey);
} }
/** /**

View File

@ -3,11 +3,6 @@ package com.ruoyi.common.utils;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date; import java.util.Date;
import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.commons.lang3.time.DateFormatUtils;
@ -136,14 +131,6 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
return new Date(time); return new Date(time);
} }
/**
* 计算相差天数
*/
public static int differentDaysByMillisecond(Date date1, Date date2)
{
return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
}
/** /**
* 计算两个时间差 * 计算两个时间差
*/ */
@ -165,23 +152,4 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
// long sec = diff % nd % nh % nm / ns; // long sec = diff % nd % nh % nm / ns;
return day + "" + hour + "小时" + min + "分钟"; return day + "" + hour + "小时" + min + "分钟";
} }
/**
* 增加 LocalDateTime ==> Date
*/
public static Date toDate(LocalDateTime temporalAccessor)
{
ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
return Date.from(zdt.toInstant());
}
/**
* 增加 LocalDate ==> Date
*/
public static Date toDate(LocalDate temporalAccessor)
{
LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
return Date.from(zdt.toInstant());
}
} }

View File

@ -41,7 +41,8 @@ public class DictUtils
Object cacheObj = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key)); Object cacheObj = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
if (StringUtils.isNotNull(cacheObj)) if (StringUtils.isNotNull(cacheObj))
{ {
return StringUtils.cast(cacheObj); List<SysDictData> dictDatas = StringUtils.cast(cacheObj);
return dictDatas;
} }
return null; return null;
} }
@ -91,7 +92,7 @@ public class DictUtils
{ {
if (value.equals(dict.getDictValue())) if (value.equals(dict.getDictValue()))
{ {
propertyString.append(dict.getDictLabel()).append(separator); propertyString.append(dict.getDictLabel() + separator);
break; break;
} }
} }
@ -131,7 +132,7 @@ public class DictUtils
{ {
if (label.equals(dict.getDictLabel())) if (label.equals(dict.getDictLabel()))
{ {
propertyString.append(dict.getDictValue()).append(separator); propertyString.append(dict.getDictValue() + separator);
break; break;
} }
} }

View File

@ -18,7 +18,8 @@ public class ExceptionUtil
{ {
StringWriter sw = new StringWriter(); StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw, true)); e.printStackTrace(new PrintWriter(sw, true));
return sw.toString(); String str = sw.toString();
return str;
} }
public static String getRootErrorMessage(Exception e) public static String getRootErrorMessage(Exception e)

View File

@ -1,36 +0,0 @@
package com.ruoyi.common.utils;
import com.github.pagehelper.PageHelper;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.utils.sql.SqlUtil;
/**
* 分页工具类
*
* @author ruoyi
*/
public class PageUtils extends PageHelper
{
/**
* 设置请求分页数据
*/
public static void
startPage()
{
PageDomain pageDomain = TableSupport.buildPageRequest();
Integer pageNum = pageDomain.getPageNum();
Integer pageSize = pageDomain.getPageSize();
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
Boolean reasonable = pageDomain.getReasonable();
PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
}
/**
* 清理分页的线程变量
*/
public static void clearPage()
{
PageHelper.clearPage();
}
}

View File

@ -99,8 +99,9 @@ public class ServletUtils
* *
* @param response 渲染对象 * @param response 渲染对象
* @param string 待渲染的字符串 * @param string 待渲染的字符串
* @return null
*/ */
public static void renderString(HttpServletResponse response, String string) public static String renderString(HttpServletResponse response, String string)
{ {
try try
{ {
@ -113,6 +114,7 @@ public class ServletUtils
{ {
e.printStackTrace(); e.printStackTrace();
} }
return null;
} }
/** /**
@ -123,13 +125,13 @@ public class ServletUtils
public static boolean isAjaxRequest(HttpServletRequest request) public static boolean isAjaxRequest(HttpServletRequest request)
{ {
String accept = request.getHeader("accept"); String accept = request.getHeader("accept");
if (accept != null && accept.contains("application/json")) if (accept != null && accept.indexOf("application/json") != -1)
{ {
return true; return true;
} }
String xRequestedWith = request.getHeader("X-Requested-With"); String xRequestedWith = request.getHeader("X-Requested-With");
if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1)
{ {
return true; return true;
} }
@ -141,6 +143,10 @@ public class ServletUtils
} }
String ajax = request.getParameter("__ajax"); String ajax = request.getParameter("__ajax");
return StringUtils.inStringIgnoreCase(ajax, "json", "xml"); if (StringUtils.inStringIgnoreCase(ajax, "json", "xml"))
{
return true;
}
return false;
} }
} }

View File

@ -531,53 +531,4 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
{ {
return (T) obj; return (T) obj;
} }
/**
* 数字左边补齐0使之达到指定长度注意如果数字转换为字符串后长度大于size则只保留 最后size个字符
*
* @param num 数字对象
* @param size 字符串指定长度
* @return 返回数字的字符串格式该字符串为指定长度
*/
public static final String padl(final Number num, final int size)
{
return padl(num.toString(), size, '0');
}
/**
* 字符串左补齐如果原始字符串s长度大于size则只保留最后size个字符
*
* @param s 原始字符串
* @param size 字符串指定长度
* @param c 用于补齐的字符
* @return 返回指定长度的字符串由原字符串左补齐或截取得到
*/
public static final String padl(final String s, final int size, final char c)
{
final StringBuilder sb = new StringBuilder(size);
if (s != null)
{
final int len = s.length();
if (s.length() <= size)
{
for (int i = size - len; i > 0; i--)
{
sb.append(c);
}
sb.append(s);
}
else
{
return s.substring(len - size, len);
}
}
else
{
for (int i = size; i > 0; i--)
{
sb.append(c);
}
}
return sb.toString();
}
} }

View File

@ -0,0 +1,228 @@
package com.ruoyi.common.utils;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Random;
import javax.imageio.ImageIO;
/**
* 验证码工具类
*
* @author ruoyi
*/
public class VerifyCodeUtils
{
// 使用到Algerian字体系统里没有的话需要安装字体字体只显示大写去掉了1,0,i,o几个容易混淆的字符
public static final String VERIFY_CODES = "123456789ABCDEFGHJKLMNPQRSTUVWXYZ";
private static Random random = new SecureRandom();
/**
* 使用系统默认字符源生成验证码
*
* @param verifySize 验证码长度
* @return
*/
public static String generateVerifyCode(int verifySize)
{
return generateVerifyCode(verifySize, VERIFY_CODES);
}
/**
* 使用指定源生成验证码
*
* @param verifySize 验证码长度
* @param sources 验证码字符源
* @return
*/
public static String generateVerifyCode(int verifySize, String sources)
{
if (sources == null || sources.length() == 0)
{
sources = VERIFY_CODES;
}
int codesLen = sources.length();
Random rand = new Random(System.currentTimeMillis());
StringBuilder verifyCode = new StringBuilder(verifySize);
for (int i = 0; i < verifySize; i++)
{
verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1)));
}
return verifyCode.toString();
}
/**
* 输出指定验证码图片流
*
* @param w
* @param h
* @param os
* @param code
* @throws IOException
*/
public static void outputImage(int w, int h, OutputStream os, String code) throws IOException
{
int verifySize = code.length();
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Random rand = new Random();
Graphics2D g2 = image.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color[] colors = new Color[5];
Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN, Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA,
Color.ORANGE, Color.PINK, Color.YELLOW };
float[] fractions = new float[colors.length];
for (int i = 0; i < colors.length; i++)
{
colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
fractions[i] = rand.nextFloat();
}
Arrays.sort(fractions);
g2.setColor(Color.GRAY);// 设置边框色
g2.fillRect(0, 0, w, h);
Color c = getRandColor(200, 250);
g2.setColor(c);// 设置背景色
g2.fillRect(0, 2, w, h - 4);
// 绘制干扰线
Random random = new Random();
g2.setColor(getRandColor(160, 200));// 设置线条的颜色
for (int i = 0; i < 20; i++)
{
int x = random.nextInt(w - 1);
int y = random.nextInt(h - 1);
int xl = random.nextInt(6) + 1;
int yl = random.nextInt(12) + 1;
g2.drawLine(x, y, x + xl + 40, y + yl + 20);
}
// 添加噪点
float yawpRate = 0.05f;// 噪声率
int area = (int) (yawpRate * w * h);
for (int i = 0; i < area; i++)
{
int x = random.nextInt(w);
int y = random.nextInt(h);
int rgb = getRandomIntColor();
image.setRGB(x, y, rgb);
}
shear(g2, w, h, c);// 使图片扭曲
g2.setColor(getRandColor(100, 160));
int fontSize = h - 4;
Font font = new Font("Algerian", Font.ITALIC, fontSize);
g2.setFont(font);
char[] chars = code.toCharArray();
for (int i = 0; i < verifySize; i++)
{
AffineTransform affine = new AffineTransform();
affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1),
(w / verifySize) * i + fontSize / 2, h / 2);
g2.setTransform(affine);
g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10);
}
g2.dispose();
ImageIO.write(image, "jpg", os);
}
private static Color getRandColor(int fc, int bc)
{
if (fc > 255) {
fc = 255;
}
if (bc > 255) {
bc = 255;
}
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}
private static int getRandomIntColor()
{
int[] rgb = getRandomRgb();
int color = 0;
for (int c : rgb)
{
color = color << 8;
color = color | c;
}
return color;
}
private static int[] getRandomRgb()
{
int[] rgb = new int[3];
for (int i = 0; i < 3; i++)
{
rgb[i] = random.nextInt(255);
}
return rgb;
}
private static void shear(Graphics g, int w1, int h1, Color color)
{
shearX(g, w1, h1, color);
shearY(g, w1, h1, color);
}
private static void shearX(Graphics g, int w1, int h1, Color color)
{
int period = random.nextInt(2);
boolean borderGap = true;
int frames = 1;
int phase = random.nextInt(2);
for (int i = 0; i < h1; i++)
{
double d = (double) (period >> 1)
* Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
g.copyArea(0, i, w1, 1, (int) d, 0);
if (borderGap)
{
g.setColor(color);
g.drawLine((int) d, i, 0, i);
g.drawLine((int) d + w1, i, w1, i);
}
}
}
private static void shearY(Graphics g, int w1, int h1, Color color)
{
int period = random.nextInt(40) + 10; // 50;
boolean borderGap = true;
int frames = 20;
int phase = 7;
for (int i = 0; i < w1; i++)
{
double d = (double) (period >> 1)
* Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
g.copyArea(i, 0, 1, h1, 0, (int) d);
if (borderGap)
{
g.setColor(color);
g.drawLine(i, (int) d, i, 0);
g.drawLine(i, (int) d + h1, i, h1);
}
}
}
}

View File

@ -1,24 +0,0 @@
package com.ruoyi.common.utils.bean;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
/**
* bean对象属性验证
*
* @author ruoyi
*/
public class BeanValidators
{
public static void validateWithException(Validator validator, Object object, Class<?>... groups)
throws ConstraintViolationException
{
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
if (!constraintViolations.isEmpty())
{
throw new ConstraintViolationException(constraintViolations);
}
}
}

View File

@ -2,8 +2,6 @@ package com.ruoyi.common.utils.file;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Paths;
import java.util.Objects;
import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.config.RuoYiConfig;
@ -13,7 +11,7 @@ import com.ruoyi.common.exception.file.FileSizeLimitExceededException;
import com.ruoyi.common.exception.file.InvalidExtensionException; import com.ruoyi.common.exception.file.InvalidExtensionException;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.Seq; import com.ruoyi.common.utils.uuid.IdUtils;
/** /**
* 文件上传工具类 * 文件上传工具类
@ -102,7 +100,7 @@ public class FileUploadUtils
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException, throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException InvalidExtensionException
{ {
int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length(); int fileNamelength = file.getOriginalFilename().length();
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
{ {
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH); throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
@ -112,9 +110,10 @@ public class FileUploadUtils
String fileName = extractFilename(file); String fileName = extractFilename(file);
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath(); File desc = getAbsoluteFile(baseDir, fileName);
file.transferTo(Paths.get(absPath)); file.transferTo(desc);
return getPathFileName(baseDir, fileName); String pathFileName = getPathFileName(baseDir, fileName);
return pathFileName;
} }
/** /**
@ -122,8 +121,10 @@ public class FileUploadUtils
*/ */
public static final String extractFilename(MultipartFile file) public static final String extractFilename(MultipartFile file)
{ {
return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(), String fileName = file.getOriginalFilename();
FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file)); String extension = getExtension(file);
fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
return fileName;
} }
public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
@ -144,7 +145,8 @@ public class FileUploadUtils
{ {
int dirLastIndex = RuoYiConfig.getProfile().length() + 1; int dirLastIndex = RuoYiConfig.getProfile().length() + 1;
String currentDir = StringUtils.substring(uploadDir, dirLastIndex); String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName; String pathFileName = Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
return pathFileName;
} }
/** /**
@ -159,7 +161,7 @@ public class FileUploadUtils
throws FileSizeLimitExceededException, InvalidExtensionException throws FileSizeLimitExceededException, InvalidExtensionException
{ {
long size = file.getSize(); long size = file.getSize();
if (size > DEFAULT_MAX_SIZE) if (DEFAULT_MAX_SIZE != -1 && size > DEFAULT_MAX_SIZE)
{ {
throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024); throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
} }
@ -226,7 +228,7 @@ public class FileUploadUtils
String extension = FilenameUtils.getExtension(file.getOriginalFilename()); String extension = FilenameUtils.getExtension(file.getOriginalFilename());
if (StringUtils.isEmpty(extension)) if (StringUtils.isEmpty(extension))
{ {
extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType())); extension = MimeTypeUtils.getExtension(file.getContentType());
} }
return extension; return extension;
} }

View File

@ -17,7 +17,6 @@ import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.IdUtils; import com.ruoyi.common.utils.uuid.IdUtils;
import org.apache.commons.io.FilenameUtils;
/** /**
* 文件处理工具类 * 文件处理工具类
@ -197,6 +196,7 @@ public class FileUtils
* *
* @param response 响应对象 * @param response 响应对象
* @param realFileName 真实文件名 * @param realFileName 真实文件名
* @return
*/ */
public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
{ {
@ -210,6 +210,7 @@ public class FileUtils
.append("utf-8''") .append("utf-8''")
.append(percentEncodedFileName); .append(percentEncodedFileName);
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename"); response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
response.setHeader("Content-disposition", contentDispositionValue.toString()); response.setHeader("Content-disposition", contentDispositionValue.toString());
response.setHeader("download-filename", percentEncodedFileName); response.setHeader("download-filename", percentEncodedFileName);
@ -255,39 +256,4 @@ public class FileUtils
} }
return strFileExtendName; return strFileExtendName;
} }
/**
* 获取文件名称 /profile/upload/2022/04/16/ruoyi.png -- ruoyi.png
*
* @param fileName 路径名称
* @return 没有文件路径的名称
*/
public static String getName(String fileName)
{
if (fileName == null)
{
return null;
}
int lastUnixPos = fileName.lastIndexOf('/');
int lastWindowsPos = fileName.lastIndexOf('\\');
int index = Math.max(lastUnixPos, lastWindowsPos);
return fileName.substring(index + 1);
}
/**
* 获取不带后缀文件名称 /profile/upload/2022/04/16/ruoyi.png -- ruoyi
*
* @param fileName 路径名称
* @return 没有文件路径和后缀的名称
*/
public static String getNameNotSuffix(String fileName)
{
if (fileName == null)
{
return null;
}
String baseName = FilenameUtils.getBaseName(fileName);
return baseName;
}
} }

View File

@ -1,6 +1,7 @@
package com.ruoyi.common.utils.file; package com.ruoyi.common.utils.file;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
@ -58,12 +59,13 @@ public class ImageUtils
/** /**
* 读取文件为字节数据 * 读取文件为字节数据
* *
* @param url 地址 * @param key 地址
* @return 字节数据 * @return 字节数据
*/ */
public static byte[] readFile(String url) public static byte[] readFile(String url)
{ {
InputStream in = null; InputStream in = null;
ByteArrayOutputStream baos = null;
try try
{ {
if (url.startsWith("http")) if (url.startsWith("http"))
@ -93,6 +95,7 @@ public class ImageUtils
finally finally
{ {
IOUtils.closeQuietly(in); IOUtils.closeQuietly(in);
IOUtils.closeQuietly(baos);
} }
} }
} }

View File

@ -1,66 +0,0 @@
package com.ruoyi.common.utils.file;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.*;
import java.util.Map;
/**
* @Author: JinSheng Song
* @Date: 2022/6/10 9:17
*/
public class WeatherUtils
{
public static String httpRequest(String requestUrl,Map params) {
//buffer用于接受返回的字符
StringBuffer buffer = new StringBuffer();
try {
//建立URL把请求地址给补全其中urlencode方法用于把params里的参数给取出来
URL url = new URL(requestUrl+"?"+urlencode(params));
//打开http连接
HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
httpUrlConn.setDoInput(true);
httpUrlConn.setRequestMethod("GET");
httpUrlConn.connect();
//获得输入
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
//将bufferReader的值给放到buffer里
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
//关闭bufferReader和输入流
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
//断开连接
httpUrlConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
//返回字符串
return buffer.toString();
}
public static String urlencode(Map<String,Object>data) {
//将map里的参数变成像 showapi_appid=###&showapi_sign=###&的样子
StringBuilder sb = new StringBuilder();
for (Map.Entry i : data.entrySet()) {
try {
sb.append(i.getKey()).append("=").append(URLEncoder.encode(i.getValue()+"","UTF-8")).append("&");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}

View File

@ -4,7 +4,7 @@ import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets; import java.nio.charset.Charset;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -25,7 +25,7 @@ public class HttpHelper
BufferedReader reader = null; BufferedReader reader = null;
try (InputStream inputStream = request.getInputStream()) try (InputStream inputStream = request.getInputStream())
{ {
reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String line = ""; String line = "";
while ((line = reader.readLine()) != null) while ((line = reader.readLine()) != null)
{ {

View File

@ -9,7 +9,6 @@ import java.net.ConnectException;
import java.net.SocketTimeoutException; import java.net.SocketTimeoutException;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.HttpsURLConnection;
@ -131,8 +130,9 @@ public class HttpUtils
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
try try
{ {
log.info("sendPost - {}", url); String urlNameString = url;
URL realUrl = new URL(url); log.info("sendPost - {}", urlNameString);
URL realUrl = new URL(urlNameString);
URLConnection conn = realUrl.openConnection(); URLConnection conn = realUrl.openConnection();
conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("connection", "Keep-Alive");
@ -144,7 +144,7 @@ public class HttpUtils
out = new PrintWriter(conn.getOutputStream()); out = new PrintWriter(conn.getOutputStream());
out.print(param); out.print(param);
out.flush(); out.flush();
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)); in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
String line; String line;
while ((line = in.readLine()) != null) while ((line = in.readLine()) != null)
{ {
@ -218,7 +218,7 @@ public class HttpUtils
{ {
if (ret != null && !"".equals(ret.trim())) if (ret != null && !"".equals(ret.trim()))
{ {
result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8)); result.append(new String(ret.getBytes("ISO-8859-1"), "utf-8"));
} }
} }
log.info("recv - {}", result); log.info("recv - {}", result);

View File

@ -25,6 +25,7 @@ public class AddressUtils
public static String getRealAddressByIP(String ip) public static String getRealAddressByIP(String ip)
{ {
String address = UNKNOWN;
// 内网不查询 // 内网不查询
if (IpUtils.internalIp(ip)) if (IpUtils.internalIp(ip))
{ {
@ -50,6 +51,6 @@ public class AddressUtils
log.error("获取地理位置异常 {}", ip); log.error("获取地理位置异常 {}", ip);
} }
} }
return UNKNOWN; return address;
} }
} }

View File

@ -4,6 +4,7 @@ import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.html.EscapeUtil;
/** /**
* 获取IP方法 * 获取IP方法
@ -12,12 +13,6 @@ import com.ruoyi.common.utils.StringUtils;
*/ */
public class IpUtils public class IpUtils
{ {
/**
* 获取客户端IP
*
* @param request 请求对象
* @return IP地址
*/
public static String getIpAddr(HttpServletRequest request) public static String getIpAddr(HttpServletRequest request)
{ {
if (request == null) if (request == null)
@ -46,28 +41,15 @@ public class IpUtils
{ {
ip = request.getRemoteAddr(); ip = request.getRemoteAddr();
} }
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : EscapeUtil.clean(ip);
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip);
} }
/**
* 检查是否为内部IP地址
*
* @param ip IP地址
* @return 结果
*/
public static boolean internalIp(String ip) public static boolean internalIp(String ip)
{ {
byte[] addr = textToNumericFormatV4(ip); byte[] addr = textToNumericFormatV4(ip);
return internalIp(addr) || "127.0.0.1".equals(ip); return internalIp(addr) || "127.0.0.1".equals(ip);
} }
/**
* 检查是否为内部IP地址
*
* @param addr byte地址
* @return 结果
*/
private static boolean internalIp(byte[] addr) private static boolean internalIp(byte[] addr)
{ {
if (StringUtils.isNull(addr) || addr.length < 2) if (StringUtils.isNull(addr) || addr.length < 2)
@ -128,8 +110,7 @@ public class IpUtils
{ {
case 1: case 1:
l = Long.parseLong(elements[0]); l = Long.parseLong(elements[0]);
if ((l < 0L) || (l > 4294967295L)) if ((l < 0L) || (l > 4294967295L)) {
{
return null; return null;
} }
bytes[0] = (byte) (int) (l >> 24 & 0xFF); bytes[0] = (byte) (int) (l >> 24 & 0xFF);
@ -139,14 +120,12 @@ public class IpUtils
break; break;
case 2: case 2:
l = Integer.parseInt(elements[0]); l = Integer.parseInt(elements[0]);
if ((l < 0L) || (l > 255L)) if ((l < 0L) || (l > 255L)) {
{
return null; return null;
} }
bytes[0] = (byte) (int) (l & 0xFF); bytes[0] = (byte) (int) (l & 0xFF);
l = Integer.parseInt(elements[1]); l = Integer.parseInt(elements[1]);
if ((l < 0L) || (l > 16777215L)) if ((l < 0L) || (l > 16777215L)) {
{
return null; return null;
} }
bytes[1] = (byte) (int) (l >> 16 & 0xFF); bytes[1] = (byte) (int) (l >> 16 & 0xFF);
@ -157,15 +136,13 @@ public class IpUtils
for (i = 0; i < 2; ++i) for (i = 0; i < 2; ++i)
{ {
l = Integer.parseInt(elements[i]); l = Integer.parseInt(elements[i]);
if ((l < 0L) || (l > 255L)) if ((l < 0L) || (l > 255L)) {
{
return null; return null;
} }
bytes[i] = (byte) (int) (l & 0xFF); bytes[i] = (byte) (int) (l & 0xFF);
} }
l = Integer.parseInt(elements[2]); l = Integer.parseInt(elements[2]);
if ((l < 0L) || (l > 65535L)) if ((l < 0L) || (l > 65535L)) {
{
return null; return null;
} }
bytes[2] = (byte) (int) (l >> 8 & 0xFF); bytes[2] = (byte) (int) (l >> 8 & 0xFF);
@ -175,8 +152,7 @@ public class IpUtils
for (i = 0; i < 4; ++i) for (i = 0; i < 4; ++i)
{ {
l = Integer.parseInt(elements[i]); l = Integer.parseInt(elements[i]);
if ((l < 0L) || (l > 255L)) if ((l < 0L) || (l > 255L)) {
{
return null; return null;
} }
bytes[i] = (byte) (int) (l & 0xFF); bytes[i] = (byte) (int) (l & 0xFF);
@ -193,11 +169,6 @@ public class IpUtils
return bytes; return bytes;
} }
/**
* 获取IP地址
*
* @return 本地IP地址
*/
public static String getHostIp() public static String getHostIp()
{ {
try try
@ -210,11 +181,6 @@ public class IpUtils
return "127.0.0.1"; return "127.0.0.1";
} }
/**
* 获取主机名
*
* @return 本地主机名
*/
public static String getHostName() public static String getHostName()
{ {
try try
@ -226,39 +192,4 @@ public class IpUtils
} }
return "未知"; return "未知";
} }
/**
* 从多级反向代理中获得第一个非unknown IP地址
*
* @param ip 获得的IP地址
* @return 第一个非unknown IP地址
*/
public static String getMultistageReverseProxyIp(String ip)
{
// 多级反向代理检测
if (ip != null && ip.indexOf(",") > 0)
{
final String[] ips = ip.trim().split(",");
for (String subIp : ips)
{
if (false == isUnknown(subIp))
{
ip = subIp;
break;
}
}
}
return ip;
}
/**
* 检测给定字符串是否为未知多用于检测HTTP请求相关
*
* @param checkString 被检测的字符串
* @return 是否未知
*/
public static boolean isUnknown(String checkString)
{
return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
}
} }

View File

@ -9,8 +9,6 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
@ -22,7 +20,6 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.RegExUtils;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor; import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFPicture; import org.apache.poi.hssf.usermodel.HSSFPicture;
import org.apache.poi.hssf.usermodel.HSSFPictureData; import org.apache.poi.hssf.usermodel.HSSFPictureData;
@ -89,10 +86,6 @@ public class ExcelUtil<T>
{ {
private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
public static final String FORMULA_REGEX_STR = "=|-|\\+|@";
public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
/** /**
* Excel sheet最大行数默认65536 * Excel sheet最大行数默认65536
*/ */
@ -319,7 +312,7 @@ public class ExcelUtil<T>
String dateFormat = field.getAnnotation(Excel.class).dateFormat(); String dateFormat = field.getAnnotation(Excel.class).dateFormat();
if (StringUtils.isNotEmpty(dateFormat)) if (StringUtils.isNotEmpty(dateFormat))
{ {
val = parseDateToStr(dateFormat, val); val = DateUtils.parseDateToStr(dateFormat, (Date) val);
} }
else else
{ {
@ -331,7 +324,7 @@ public class ExcelUtil<T>
{ {
val = Convert.toInt(val); val = Convert.toInt(val);
} }
else if ((Long.TYPE == fieldType || Long.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) else if (Long.TYPE == fieldType || Long.class == fieldType)
{ {
val = Convert.toLong(val); val = Convert.toLong(val);
} }
@ -436,6 +429,7 @@ public class ExcelUtil<T>
* @param list 导出数据集合 * @param list 导出数据集合
* @param sheetName 工作表的名称 * @param sheetName 工作表的名称
* @return 结果 * @return 结果
* @throws IOException
*/ */
public void exportExcel(HttpServletResponse response, List<T> list, String sheetName) public void exportExcel(HttpServletResponse response, List<T> list, String sheetName)
{ {
@ -450,6 +444,7 @@ public class ExcelUtil<T>
* @param sheetName 工作表的名称 * @param sheetName 工作表的名称
* @param title 标题 * @param title 标题
* @return 结果 * @return 结果
* @throws IOException
*/ */
public void exportExcel(HttpServletResponse response, List<T> list, String sheetName, String title) public void exportExcel(HttpServletResponse response, List<T> list, String sheetName, String title)
{ {
@ -672,46 +667,21 @@ public class ExcelUtil<T>
style.setFont(totalFont); style.setFont(totalFont);
styles.put("total", style); styles.put("total", style);
styles.putAll(annotationStyles(wb));
return styles;
}
/**
* 根据Excel注解创建表格样式
*
* @param wb 工作薄对象
* @return 自定义样式列表
*/
private Map<String, CellStyle> annotationStyles(Workbook wb)
{
Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
for (Object[] os : fields)
{
Excel excel = (Excel) os[1];
String key = "data_" + excel.align() + "_" + excel.color();
if (!styles.containsKey(key))
{
CellStyle style = wb.createCellStyle();
style = wb.createCellStyle(); style = wb.createCellStyle();
style.setAlignment(excel.align()); style.cloneStyleFrom(styles.get("data"));
style.setVerticalAlignment(VerticalAlignment.CENTER); style.setAlignment(HorizontalAlignment.LEFT);
style.setBorderRight(BorderStyle.THIN); styles.put("data1", style);
style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderLeft(BorderStyle.THIN); style = wb.createCellStyle();
style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); style.cloneStyleFrom(styles.get("data"));
style.setBorderTop(BorderStyle.THIN); style.setAlignment(HorizontalAlignment.CENTER);
style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); styles.put("data2", style);
style.setBorderBottom(BorderStyle.THIN);
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); style = wb.createCellStyle();
Font dataFont = wb.createFont(); style.cloneStyleFrom(styles.get("data"));
dataFont.setFontName("Arial"); style.setAlignment(HorizontalAlignment.RIGHT);
dataFont.setFontHeightInPoints((short) 10); styles.put("data3", style);
dataFont.setColor(excel.color().index);
style.setFont(dataFont);
styles.put(key, style);
}
}
return styles; return styles;
} }
@ -740,13 +710,7 @@ public class ExcelUtil<T>
{ {
if (ColumnType.STRING == attr.cellType()) if (ColumnType.STRING == attr.cellType())
{ {
String cellValue = Convert.toStr(value); cell.setCellValue(StringUtils.isNull(value) ? attr.defaultValue() : value + attr.suffix());
// 对于任何以表达式触发字符 =-+@开头的单元格直接使用tab字符作为前缀防止CSV注入
if (StringUtils.startsWithAny(cellValue, FORMULA_STR))
{
cellValue = RegExUtils.replaceFirst(cellValue, FORMULA_REGEX_STR, "\t$0");
}
cell.setCellValue(StringUtils.isNull(cellValue) ? attr.defaultValue() : cellValue + attr.suffix());
} }
else if (ColumnType.NUMERIC == attr.cellType()) else if (ColumnType.NUMERIC == attr.cellType())
{ {
@ -811,10 +775,17 @@ public class ExcelUtil<T>
// 设置列宽 // 设置列宽
sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256)); sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
} }
if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0) // 如果设置了提示信息则鼠标放上去提示.
if (StringUtils.isNotEmpty(attr.prompt()))
{ {
// 提示信息或只能选择不能输入的列内容. // 这里默认设了2-101列提示.
setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column); setXSSFPrompt(sheet, "", attr.prompt(), 1, 100, column, column);
}
// 如果设置了combo属性则本列只能选择不能输入
if (attr.combo().length > 0)
{
// 这里默认设了2-101列只能选择不能输入.
setXSSFValidation(sheet, attr.combo(), 1, 100, column, column);
} }
} }
@ -833,7 +804,8 @@ public class ExcelUtil<T>
{ {
// 创建cell // 创建cell
cell = row.createCell(column); cell = row.createCell(column);
cell.setCellStyle(styles.get("data_" + attr.align() + "_" + attr.color())); int align = attr.align().value();
cell.setCellStyle(styles.get("data" + (align >= 1 && align <= 3 ? align : "")));
// 用于读取对象中的属性 // 用于读取对象中的属性
Object value = getTargetValue(vo, field, attr); Object value = getTargetValue(vo, field, attr);
@ -843,7 +815,7 @@ public class ExcelUtil<T>
String dictType = attr.dictType(); String dictType = attr.dictType();
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
{ {
cell.setCellValue(parseDateToStr(dateFormat, value)); cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value));
} }
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
{ {
@ -877,29 +849,48 @@ public class ExcelUtil<T>
} }
/** /**
* 设置 POI XSSFSheet 单元格提示或选择框 * 设置 POI XSSFSheet 单元格提示
* *
* @param sheet 表单 * @param sheet 表单
* @param textlist 下拉框显示的内容 * @param promptTitle 提示标题
* @param promptContent 提示内容 * @param promptContent 提示内容
* @param firstRow 开始行 * @param firstRow 开始行
* @param endRow 结束行 * @param endRow 结束行
* @param firstCol 开始列 * @param firstCol 开始列
* @param endCol 结束列 * @param endCol 结束列
*/ */
public void setPromptOrValidation(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, public void setXSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow,
int firstCol, int endCol) int firstCol, int endCol)
{ {
DataValidationHelper helper = sheet.getDataValidationHelper(); DataValidationHelper helper = sheet.getDataValidationHelper();
DataValidationConstraint constraint = textlist.length > 0 ? helper.createExplicitListConstraint(textlist) : helper.createCustomConstraint("DD1"); DataValidationConstraint constraint = helper.createCustomConstraint("DD1");
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
DataValidation dataValidation = helper.createValidation(constraint, regions); DataValidation dataValidation = helper.createValidation(constraint, regions);
if (StringUtils.isNotEmpty(promptContent)) dataValidation.createPromptBox(promptTitle, promptContent);
{
// 如果设置了提示信息则鼠标放上去提示
dataValidation.createPromptBox("", promptContent);
dataValidation.setShowPromptBox(true); dataValidation.setShowPromptBox(true);
sheet.addValidationData(dataValidation);
} }
/**
* 设置某些列的值只能输入预制的数据,显示下拉框.
*
* @param sheet 要设置的sheet.
* @param textlist 下拉框显示的内容
* @param firstRow 开始行
* @param endRow 结束行
* @param firstCol 开始列
* @param endCol 结束列
* @return 设置好的sheet.
*/
public void setXSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol)
{
DataValidationHelper helper = sheet.getDataValidationHelper();
// 加载下拉列表内容
DataValidationConstraint constraint = helper.createExplicitListConstraint(textlist);
// 设置数据有效性加载在哪个单元格上,四个参数分别是起始行终止行起始列终止列
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
// 数据有效性对象
DataValidation dataValidation = helper.createValidation(constraint, regions);
// 处理Excel兼容性问题 // 处理Excel兼容性问题
if (dataValidation instanceof XSSFDataValidation) if (dataValidation instanceof XSSFDataValidation)
{ {
@ -910,6 +901,7 @@ public class ExcelUtil<T>
{ {
dataValidation.setSuppressDropDownArrow(false); dataValidation.setSuppressDropDownArrow(false);
} }
sheet.addValidationData(dataValidation); sheet.addValidationData(dataValidation);
} }
@ -1121,7 +1113,7 @@ public class ExcelUtil<T>
if (StringUtils.isNotEmpty(excel.targetAttr())) if (StringUtils.isNotEmpty(excel.targetAttr()))
{ {
String target = excel.targetAttr(); String target = excel.targetAttr();
if (target.contains(".")) if (target.indexOf(".") > -1)
{ {
String[] targets = target.split("[.]"); String[] targets = target.split("[.]");
for (String name : targets) for (String name : targets)
@ -1216,7 +1208,7 @@ public class ExcelUtil<T>
for (Object[] os : this.fields) for (Object[] os : this.fields)
{ {
Excel excel = (Excel) os[1]; Excel excel = (Excel) os[1];
maxHeight = Math.max(maxHeight, excel.height()); maxHeight = maxHeight > excel.height() ? maxHeight : excel.height();
} }
return (short) (maxHeight * 20); return (short) (maxHeight * 20);
} }
@ -1396,37 +1388,4 @@ public class ExcelUtil<T>
} }
return sheetIndexPicMap; return sheetIndexPicMap;
} }
/**
* 格式化不同类型的日期对象
*
* @param dateFormat 日期格式
* @param val 被格式化的日期对象
* @return 格式化后的日期字符
*/
public String parseDateToStr(String dateFormat, Object val)
{
if (val == null)
{
return "";
}
String str;
if (val instanceof Date)
{
str = DateUtils.parseDateToStr(dateFormat, (Date) val);
}
else if (val instanceof LocalDateTime)
{
str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDateTime) val));
}
else if (val instanceof LocalDate)
{
str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDate) val));
}
else
{
str = val.toString();
}
return str;
}
} }

View File

@ -1,6 +1,5 @@
package com.ruoyi.common.utils.sign; package com.ruoyi.common.utils.sign;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest; import java.security.MessageDigest;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -56,7 +55,7 @@ public class Md5Utils
{ {
try try
{ {
return new String(toHex(md5(s)).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8); return new String(toHex(md5(s)).getBytes("UTF-8"), "UTF-8");
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -10,11 +10,6 @@ import com.ruoyi.common.utils.StringUtils;
*/ */
public class SqlUtil public class SqlUtil
{ {
/**
* 定义常用的 sql关键字
*/
public static String SQL_REGEX = "select |insert |delete |update |drop |count |exec |chr |mid |master |truncate |char |and |declare ";
/** /**
* 仅支持字母数字下划线空格逗号小数点支持多个字段排序 * 仅支持字母数字下划线空格逗号小数点支持多个字段排序
*/ */
@ -39,23 +34,4 @@ public class SqlUtil
{ {
return value.matches(SQL_PATTERN); return value.matches(SQL_PATTERN);
} }
/**
* SQL关键字检查
*/
public static void filterKeyword(String value)
{
if (StringUtils.isEmpty(value))
{
return;
}
String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
for (String sqlKeyword : sqlKeywords)
{
if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1)
{
throw new UtilException("参数存在SQL注入风险");
}
}
}
} }

View File

@ -1,86 +0,0 @@
package com.ruoyi.common.utils.uuid;
import java.util.concurrent.atomic.AtomicInteger;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
/**
* @author ruoyi 序列生成类
*/
public class Seq
{
// 通用序列类型
public static final String commSeqType = "COMMON";
// 上传序列类型
public static final String uploadSeqType = "UPLOAD";
// 通用接口序列数
private static AtomicInteger commSeq = new AtomicInteger(1);
// 上传接口序列数
private static AtomicInteger uploadSeq = new AtomicInteger(1);
// 机器标识
private static String machineCode = "A";
/**
* 获取通用序列号
*
* @return 序列值
*/
public static String getId()
{
return getId(commSeqType);
}
/**
* 默认16位序列号 yyMMddHHmmss + 一位机器标识 + 3长度循环递增字符串
*
* @return 序列值
*/
public static String getId(String type)
{
AtomicInteger atomicInt = commSeq;
if (uploadSeqType.equals(type))
{
atomicInt = uploadSeq;
}
return getId(atomicInt, 3);
}
/**
* 通用接口序列号 yyMMddHHmmss + 一位机器标识 + length长度循环递增字符串
*
* @param atomicInt 序列数
* @param length 数值长度
* @return 序列值
*/
public static String getId(AtomicInteger atomicInt, int length)
{
String result = DateUtils.dateTimeNow();
result += machineCode;
result += getSeq(atomicInt, length);
return result;
}
/**
* 序列循环递增字符串[1, 10 (length)幂次方), 用0左补齐length位数
*
* @return 序列值
*/
private synchronized static String getSeq(AtomicInteger atomicInt, int length)
{
// 先取值再+1
int value = atomicInt.getAndIncrement();
// 如果更新后值>=10 (length)幂次方则重置为1
int maxSeq = (int) Math.pow(10, length);
if (atomicInt.get() >= maxSeq)
{
atomicInt.set(1);
}
// 转字符串用0左补齐
return StringUtils.padl(value, length);
}
}

View File

@ -1,27 +0,0 @@
package com.ruoyi.common.xss;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义xss校验注解
*
* @author ruoyi
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value = { ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER })
@Constraint(validatedBy = { XssValidator.class })
public @interface Xss
{
String message()
default "不允许任何脚本运行";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}

View File

@ -1,34 +0,0 @@
package com.ruoyi.common.xss;
import com.ruoyi.common.utils.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 自定义xss校验注解实现
*
* @author ruoyi
*/
public class XssValidator implements ConstraintValidator<Xss, String>
{
private static final String HTML_PATTERN = "<(\\S*?)[^>]*>.*?|<.*? />";
@Override
public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext)
{
if (StringUtils.isBlank(value))
{
return true;
}
return !containsHtml(value);
}
public static boolean containsHtml(String value)
{
Pattern pattern = Pattern.compile(HTML_PATTERN);
Matcher matcher = pattern.matcher(value);
return matcher.matches();
}
}

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.8.2</version> <version>3.8.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -35,25 +35,17 @@
<artifactId>druid-spring-boot-starter</artifactId> <artifactId>druid-spring-boot-starter</artifactId>
</dependency> </dependency>
<!-- 滑块验证码-->
<dependency>
<groupId>com.github.anji-plus</groupId>
<artifactId>captcha-spring-boot-starter</artifactId>
<version>1.2.7</version>
</dependency>
<!-- 验证码 --> <!-- 验证码 -->
<!-- <dependency>--> <dependency>
<!-- <groupId>com.github.penggle</groupId>--> <groupId>com.github.penggle</groupId>
<!-- <artifactId>kaptcha</artifactId>--> <artifactId>kaptcha</artifactId>
<!-- <exclusions>--> <exclusions>
<!-- <exclusion>--> <exclusion>
<!-- <artifactId>javax.servlet-api</artifactId>--> <artifactId>javax.servlet-api</artifactId>
<!-- <groupId>javax.servlet</groupId>--> <groupId>javax.servlet</groupId>
<!-- </exclusion>--> </exclusion>
<!-- </exclusions>--> </exclusions>
<!-- </dependency>--> </dependency>
<!-- 获取系统信息 --> <!-- 获取系统信息 -->
<dependency> <dependency>

View File

@ -65,6 +65,7 @@ public class LogAspect
{ {
try try
{ {
// 获取当前的用户 // 获取当前的用户
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();

View File

@ -0,0 +1,83 @@
package com.ruoyi.framework.config;
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import static com.google.code.kaptcha.Constants.*;
/**
* 验证码配置
*
* @author ruoyi
*/
@Configuration
public class CaptchaConfig
{
@Bean(name = "captchaProducer")
public DefaultKaptcha getKaptchaBean()
{
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yesno
properties.setProperty(KAPTCHA_BORDER, "yes");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
// 验证码图片宽度 默认为200
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
// 验证码图片高度 默认为50
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
// 验证码文本字符大小 默认为40
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
// KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
// 验证码文本字符长度 默认为5
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
@Bean(name = "captchaProducerMath")
public DefaultKaptcha getKaptchaBeanMath()
{
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yesno
properties.setProperty(KAPTCHA_BORDER, "yes");
// 边框颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
// 验证码图片宽度 默认为200
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
// 验证码图片高度 默认为50
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
// 验证码文本字符大小 默认为40
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
// KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
// 验证码文本生成器
properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.framework.config.KaptchaTextCreator");
// 验证码文本字符间距 默认为2
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
// 验证码文本字符长度 默认为5
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 验证码噪点颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
// 干扰实现类
properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}

View File

@ -0,0 +1,75 @@
package com.ruoyi.framework.config;
import java.util.Random;
import com.google.code.kaptcha.text.impl.DefaultTextCreator;
/**
* 验证码文本生成器
*
* @author ruoyi
*/
public class KaptchaTextCreator extends DefaultTextCreator
{
private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
@Override
public String getText()
{
Integer result = 0;
Random random = new Random();
int x = random.nextInt(10);
int y = random.nextInt(10);
StringBuilder suChinese = new StringBuilder();
int randomoperands = (int) Math.round(Math.random() * 2);
if (randomoperands == 0)
{
result = x * y;
suChinese.append(CNUMBERS[x]);
suChinese.append("*");
suChinese.append(CNUMBERS[y]);
}
else if (randomoperands == 1)
{
if (!(x == 0) && y % x == 0)
{
result = y / x;
suChinese.append(CNUMBERS[y]);
suChinese.append("/");
suChinese.append(CNUMBERS[x]);
}
else
{
result = x + y;
suChinese.append(CNUMBERS[x]);
suChinese.append("+");
suChinese.append(CNUMBERS[y]);
}
}
else if (randomoperands == 2)
{
if (x >= y)
{
result = x - y;
suChinese.append(CNUMBERS[x]);
suChinese.append("-");
suChinese.append(CNUMBERS[y]);
}
else
{
result = y - x;
suChinese.append(CNUMBERS[y]);
suChinese.append("-");
suChinese.append(CNUMBERS[x]);
}
}
else
{
result = x + y;
suChinese.append(CNUMBERS[x]);
suChinese.append("+");
suChinese.append(CNUMBERS[y]);
}
suChinese.append("=?@" + result);
return suChinese.toString();
}
}

View File

@ -97,8 +97,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
// 过滤请求 // 过滤请求
.authorizeRequests() .authorizeRequests()
// 对于登录login 注册register 验证码captchaImage 允许匿名访问 // 对于登录login 注册register 验证码captchaImage 允许匿名访问
// .antMatchers("/login", "/register", "/captchaImage").anonymous() .antMatchers("/login", "/register", "/captchaImage").anonymous()
.antMatchers("/login", "/register", "/captcha/get", "/captcha/check").permitAll()
.antMatchers( .antMatchers(
HttpMethod.GET, HttpMethod.GET,
"/", "/",
@ -111,7 +110,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
.antMatchers("/swagger-ui.html").anonymous() .antMatchers("/swagger-ui.html").anonymous()
.antMatchers("/swagger-resources/**").anonymous() .antMatchers("/swagger-resources/**").anonymous()
.antMatchers("/webjars/**").anonymous() .antMatchers("/webjars/**").anonymous()
.antMatchers("/login", "/captcha/get", "/captcha/check").permitAll()
.antMatchers("/*/api-docs").anonymous() .antMatchers("/*/api-docs").anonymous()
.antMatchers("/druid/**").anonymous() .antMatchers("/druid/**").anonymous()
// 除上面外的所有请求全部需要鉴权认证 // 除上面外的所有请求全部需要鉴权认证

View File

@ -1,13 +1,13 @@
package com.ruoyi.framework.config; package com.ruoyi.framework.config;
import com.ruoyi.common.utils.Threads; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import org.apache.commons.lang3.concurrent.BasicThreadFactory; import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ScheduledExecutorService; import com.ruoyi.common.utils.Threads;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
/** /**
* 线程池配置 * 线程池配置
@ -49,8 +49,7 @@ public class ThreadPoolConfig
protected ScheduledExecutorService scheduledExecutorService() protected ScheduledExecutorService scheduledExecutorService()
{ {
return new ScheduledThreadPoolExecutor(corePoolSize, return new ScheduledThreadPoolExecutor(corePoolSize,
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(), new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build())
new ThreadPoolExecutor.CallerRunsPolicy())
{ {
@Override @Override
protected void afterExecute(Runnable r, Throwable t) protected void afterExecute(Runnable r, Throwable t)

View File

@ -60,10 +60,14 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
String url = request.getRequestURI(); String url = request.getRequestURI();
// 唯一值没有消息头则使用请求地址 // 唯一值没有消息头则使用请求地址
String submitKey = StringUtils.trimToEmpty(request.getHeader(header)); String submitKey = request.getHeader(header);
if (StringUtils.isEmpty(submitKey))
{
submitKey = url;
}
// 唯一标识指定key + url + 消息头 // 唯一标识指定key + 消息头
String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + url + submitKey; String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + submitKey;
Object sessionObj = redisCache.getCacheObject(cacheRepeatKey); Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
if (sessionObj != null) if (sessionObj != null)

View File

@ -119,12 +119,4 @@ public class Jvm
{ {
return DateUtils.getDatePoor(DateUtils.getNowDate(), DateUtils.getServerStartDate()); return DateUtils.getDatePoor(DateUtils.getNowDate(), DateUtils.getServerStartDate());
} }
/**
* 运行参数
*/
public String getInputArgs()
{
return ManagementFactory.getRuntimeMXBean().getInputArguments().toString();
}
} }

View File

@ -1,53 +0,0 @@
package com.ruoyi.framework.web.service;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import com.anji.captcha.service.CaptchaCacheService;
/**
* 自定义redis验证码缓存实现类
*
* @author ruoyi
*/
public class CaptchaRedisService implements CaptchaCacheService
{
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public void set(String key, String value, long expiresInSeconds)
{
stringRedisTemplate.opsForValue().set(key, value, expiresInSeconds, TimeUnit.SECONDS);
}
@Override
public boolean exists(String key)
{
return stringRedisTemplate.hasKey(key);
}
@Override
public void delete(String key)
{
stringRedisTemplate.delete(key);
}
@Override
public String get(String key)
{
return stringRedisTemplate.opsForValue().get(key);
}
@Override
public Long increment(String key, long val)
{
return stringRedisTemplate.opsForValue().increment(key, val);
}
@Override
public String type()
{
return "redis";
}
}

View File

@ -2,20 +2,18 @@ package com.ruoyi.framework.web.service;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.user.CaptchaException; import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.CaptchaExpireException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException; import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.MessageUtils;
@ -23,6 +21,7 @@ import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.ip.IpUtils; import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.framework.manager.AsyncManager; import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory; import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;
/** /**
@ -39,12 +38,14 @@ public class SysLoginService
@Resource @Resource
private AuthenticationManager authenticationManager; private AuthenticationManager authenticationManager;
@Autowired
private RedisCache redisCache;
@Autowired @Autowired
private ISysUserService userService; private ISysUserService userService;
@Autowired @Autowired
@Lazy private ISysConfigService configService;
private CaptchaService captchaService;
/** /**
* 登录验证 * 登录验证
@ -52,18 +53,16 @@ public class SysLoginService
* @param username 用户名 * @param username 用户名
* @param password 密码 * @param password 密码
* @param code 验证码 * @param code 验证码
* @param uuid 唯一标识
* @return 结果 * @return 结果
*/ */
public String login(String username, String password, String code) public String login(String username, String password, String code, String uuid)
{ {
CaptchaVO captchaVO = new CaptchaVO(); boolean captchaOnOff = configService.selectCaptchaOnOff();
captchaVO.setCaptchaVerification(code); // 验证码开关
ResponseModel response = captchaService.verification(captchaVO); if (captchaOnOff)
if (!response.isSuccess())
{ {
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, validateCaptcha(username, code, uuid);
MessageUtils.message("user.jcaptcha.error")));
throw new CaptchaException();
} }
// 用户验证 // 用户验证
Authentication authentication = null; Authentication authentication = null;
@ -88,10 +87,36 @@ public class SysLoginService
} }
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
LoginUser loginUser = (LoginUser) authentication.getPrincipal(); LoginUser loginUser = (LoginUser) authentication.getPrincipal();
recordLoginInfo(loginUser.getUserId());
// 生成token // 生成token
return tokenService.createToken(loginUser); return tokenService.createToken(loginUser);
} }
/**
* 校验验证码
*
* @param username 用户名
* @param code 验证码
* @param uuid 唯一标识
* @return 结果
*/
public void validateCaptcha(String username, String code, String uuid)
{
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
String captcha = redisCache.getCacheObject(verifyKey);
redisCache.deleteObject(verifyKey);
if (captcha == null)
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
throw new CaptchaExpireException();
}
if (!code.equalsIgnoreCase(captcha))
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
throw new CaptchaException();
}
}
/** /**
* 记录登录信息 * 记录登录信息
* *

View File

@ -41,12 +41,12 @@ public class SysRegisterService
{ {
String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword(); String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword();
// boolean captchaOnOff = configService.selectCaptchaOnOff(); boolean captchaOnOff = configService.selectCaptchaOnOff();
// // 验证码开关 // 验证码开关
// if (captchaOnOff) if (captchaOnOff)
// { {
// validateCaptcha(username, registerBody.getCode(), registerBody.getUuid()); validateCaptcha(username, registerBody.getCode(), registerBody.getUuid());
// } }
if (StringUtils.isEmpty(username)) if (StringUtils.isEmpty(username))
{ {
@ -56,16 +56,16 @@ public class SysRegisterService
{ {
msg = "用户密码不能为空"; msg = "用户密码不能为空";
} }
// else if (username.length() < UserConstants.USERNAME_MIN_LENGTH else if (username.length() < UserConstants.USERNAME_MIN_LENGTH
// || username.length() > UserConstants.USERNAME_MAX_LENGTH) || username.length() > UserConstants.USERNAME_MAX_LENGTH)
// { {
// msg = "账户长度必须在2到20个字符之间"; msg = "账户长度必须在2到20个字符之间";
// } }
// else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
// || password.length() > UserConstants.PASSWORD_MAX_LENGTH) || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
// { {
// msg = "密码长度必须在5到20个字符之间"; msg = "密码长度必须在5到20个字符之间";
// } }
else if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(username))) else if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(username)))
{ {
msg = "保存用户'" + username + "'失败,注册账号已存在"; msg = "保存用户'" + username + "'失败,注册账号已存在";
@ -89,6 +89,7 @@ public class SysRegisterService
} }
return msg; return msg;
} }
/** /**
* 校验验证码 * 校验验证码
* *
@ -99,7 +100,7 @@ public class SysRegisterService
*/ */
public void validateCaptcha(String username, String code, String uuid) public void validateCaptcha(String username, String code, String uuid)
{ {
String verifyKey = Constants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
String captcha = redisCache.getCacheObject(verifyKey); String captcha = redisCache.getCacheObject(verifyKey);
redisCache.deleteObject(verifyKey); redisCache.deleteObject(verifyKey);
if (captcha == null) if (captcha == null)

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.8.2</version> <version>3.8.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -59,12 +59,12 @@ public class GenController extends BaseController
* 修改代码生成业务 * 修改代码生成业务
*/ */
@PreAuthorize("@ss.hasPermi('tool:gen:query')") @PreAuthorize("@ss.hasPermi('tool:gen:query')")
@GetMapping(value = "/{tableId}") @GetMapping(value = "/{talbleId}")
public AjaxResult getInfo(@PathVariable Long tableId) public AjaxResult getInfo(@PathVariable Long talbleId)
{ {
GenTable table = genTableService.selectGenTableById(tableId); GenTable table = genTableService.selectGenTableById(talbleId);
List<GenTable> tables = genTableService.selectGenTableAll(); List<GenTable> tables = genTableService.selectGenTableAll();
List<GenTableColumn> list = genTableColumnService.selectGenTableColumnListByTableId(tableId); List<GenTableColumn> list = genTableColumnService.selectGenTableColumnListByTableId(talbleId);
Map<String, Object> map = new HashMap<String, Object>(); Map<String, Object> map = new HashMap<String, Object>();
map.put("info", table); map.put("info", table);
map.put("rows", list); map.put("rows", list);
@ -88,7 +88,7 @@ public class GenController extends BaseController
* 查询数据表字段列表 * 查询数据表字段列表
*/ */
@PreAuthorize("@ss.hasPermi('tool:gen:list')") @PreAuthorize("@ss.hasPermi('tool:gen:list')")
@GetMapping(value = "/column/{tableId}") @GetMapping(value = "/column/{talbleId}")
public TableDataInfo columnList(Long tableId) public TableDataInfo columnList(Long tableId)
{ {
TableDataInfo dataInfo = new TableDataInfo(); TableDataInfo dataInfo = new TableDataInfo();

View File

@ -7,7 +7,6 @@ import java.io.StringWriter;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
@ -287,7 +286,7 @@ public class GenTableServiceImpl implements IGenTableService
{ {
GenTable table = genTableMapper.selectGenTableByName(tableName); GenTable table = genTableMapper.selectGenTableByName(tableName);
List<GenTableColumn> tableColumns = table.getColumns(); List<GenTableColumn> tableColumns = table.getColumns();
Map<String, GenTableColumn> tableColumnMap = tableColumns.stream().collect(Collectors.toMap(GenTableColumn::getColumnName, Function.identity())); List<String> tableColumnNames = tableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName); List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
if (StringUtils.isEmpty(dbTableColumns)) if (StringUtils.isEmpty(dbTableColumns))
@ -297,29 +296,9 @@ public class GenTableServiceImpl implements IGenTableService
List<String> dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList()); List<String> dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
dbTableColumns.forEach(column -> { dbTableColumns.forEach(column -> {
if (!tableColumnNames.contains(column.getColumnName()))
{
GenUtils.initColumnField(column, table); GenUtils.initColumnField(column, table);
if (tableColumnMap.containsKey(column.getColumnName()))
{
GenTableColumn prevColumn = tableColumnMap.get(column.getColumnName());
column.setColumnId(prevColumn.getColumnId());
if (column.isList())
{
// 如果是列表继续保留查询方式/字典类型选项
column.setDictType(prevColumn.getDictType());
column.setQueryType(prevColumn.getQueryType());
}
if (StringUtils.isNotEmpty(prevColumn.getIsRequired()) && !column.isPk()
&& (column.isInsert() || column.isEdit())
&& ((column.isUsableColumn()) || (!column.isSuperColumn())))
{
// 如果是(新增/修改&非主键/非忽略及父属性)继续保留必填/显示类型选项
column.setIsRequired(prevColumn.getIsRequired());
column.setHtmlType(prevColumn.getHtmlType());
}
genTableColumnMapper.updateGenTableColumn(column);
}
else
{
genTableColumnMapper.insertGenTableColumn(column); genTableColumnMapper.insertGenTableColumn(column);
} }
}); });

View File

@ -42,7 +42,6 @@ public class GenUtils
column.setJavaField(StringUtils.toCamelCase(columnName)); column.setJavaField(StringUtils.toCamelCase(columnName));
// 设置默认类型 // 设置默认类型
column.setJavaType(GenConstants.TYPE_STRING); column.setJavaType(GenConstants.TYPE_STRING);
column.setQueryType(GenConstants.QUERY_EQ);
if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType)) if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType))
{ {
@ -152,7 +151,8 @@ public class GenUtils
{ {
int lastIndex = packageName.lastIndexOf("."); int lastIndex = packageName.lastIndexOf(".");
int nameLength = packageName.length(); int nameLength = packageName.length();
return StringUtils.substring(packageName, lastIndex + 1, nameLength); String moduleName = StringUtils.substring(packageName, lastIndex + 1, nameLength);
return moduleName;
} }
/** /**
@ -165,7 +165,8 @@ public class GenUtils
{ {
int lastIndex = tableName.lastIndexOf("_"); int lastIndex = tableName.lastIndexOf("_");
int nameLength = tableName.length(); int nameLength = tableName.length();
return StringUtils.substring(tableName, lastIndex + 1, nameLength); String businessName = StringUtils.substring(tableName, lastIndex + 1, nameLength);
return businessName;
} }
/** /**

View File

@ -3,7 +3,6 @@ package com.ruoyi.generator.util;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import org.apache.velocity.VelocityContext; import org.apache.velocity.VelocityContext;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.GenConstants; import com.ruoyi.common.constant.GenConstants;
@ -228,7 +227,8 @@ public class VelocityUtils
public static String getPackagePrefix(String packageName) public static String getPackagePrefix(String packageName)
{ {
int lastIndex = packageName.lastIndexOf("."); int lastIndex = packageName.lastIndexOf(".");
return StringUtils.substring(packageName, 0, lastIndex); String basePackage = StringUtils.substring(packageName, 0, lastIndex);
return basePackage;
} }
/** /**
@ -270,24 +270,7 @@ public class VelocityUtils
public static String getDicts(GenTable genTable) public static String getDicts(GenTable genTable)
{ {
List<GenTableColumn> columns = genTable.getColumns(); List<GenTableColumn> columns = genTable.getColumns();
Set<String> dicts = new HashSet<String>(); List<String> dicts = new ArrayList<String>();
addDicts(dicts, columns);
if (StringUtils.isNotNull(genTable.getSubTable()))
{
List<GenTableColumn> subColumns = genTable.getSubTable().getColumns();
addDicts(dicts, subColumns);
}
return StringUtils.join(dicts, ", ");
}
/**
* 添加字典列表
*
* @param dicts 字典列表
* @param columns 列集合
*/
public static void addDicts(Set<String> dicts, List<GenTableColumn> columns)
{
for (GenTableColumn column : columns) for (GenTableColumn column : columns)
{ {
if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny( if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny(
@ -297,6 +280,7 @@ public class VelocityUtils
dicts.add("'" + column.getDictType() + "'"); dicts.add("'" + column.getDictType() + "'");
} }
} }
return StringUtils.join(dicts, ", ");
} }
/** /**

View File

@ -85,7 +85,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="dictType != null and dictType != ''">#{dictType},</if> <if test="dictType != null and dictType != ''">#{dictType},</if>
<if test="sort != null">#{sort},</if> <if test="sort != null">#{sort},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if> <if test="createBy != null and createBy != ''">#{createBy},</if>
current_timestamp sysdate()
) )
</insert> </insert>
@ -105,7 +105,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
dict_type = #{dictType}, dict_type = #{dictType},
sort = #{sort}, sort = #{sort},
update_by = #{updateBy}, update_by = #{updateBy},
update_time = current_timestamp update_time = sysdate()
</set> </set>
where column_id = #{columnId} where column_id = #{columnId}
</update> </update>

View File

@ -164,7 +164,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="genPath != null and genPath != ''">#{genPath},</if> <if test="genPath != null and genPath != ''">#{genPath},</if>
<if test="remark != null and remark != ''">#{remark},</if> <if test="remark != null and remark != ''">#{remark},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if> <if test="createBy != null and createBy != ''">#{createBy},</if>
current_timestamp sysdate()
) )
</insert> </insert>
@ -187,7 +187,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="options != null and options != ''">options = #{options},</if> <if test="options != null and options != ''">options = #{options},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if> <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
<if test="remark != null">remark = #{remark},</if> <if test="remark != null">remark = #{remark},</if>
update_time = current_timestamp update_time = sysdate()
</set> </set>
where table_id = #{tableId} where table_id = #{tableId}
</update> </update>

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
#foreach($column in $columns) #foreach($column in $columns)
#if($column.query) #if($column.query)
#set($dictType=$column.dictType) #set($dictType=$column.dictType)
@ -17,12 +17,13 @@
v-model="queryParams.${column.javaField}" v-model="queryParams.${column.javaField}"
placeholder="请输入${comment}" placeholder="请输入${comment}"
clearable clearable
size="small"
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType) #elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
<el-form-item label="${comment}" prop="${column.javaField}"> <el-form-item label="${comment}" prop="${column.javaField}">
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable> <el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable size="small">
<el-option <el-option
v-for="dict in dict.type.${dictType}" v-for="dict in dict.type.${dictType}"
:key="dict.value" :key="dict.value"
@ -33,13 +34,13 @@
</el-form-item> </el-form-item>
#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType) #elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
<el-form-item label="${comment}" prop="${column.javaField}"> <el-form-item label="${comment}" prop="${column.javaField}">
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable> <el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable size="small">
<el-option label="请选择字典生成" value="" /> <el-option label="请选择字典生成" value="" />
</el-select> </el-select>
</el-form-item> </el-form-item>
#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN") #elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
<el-form-item label="${comment}" prop="${column.javaField}"> <el-form-item label="${comment}" prop="${column.javaField}">
<el-date-picker clearable <el-date-picker clearable size="small"
v-model="queryParams.${column.javaField}" v-model="queryParams.${column.javaField}"
type="date" type="date"
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd"
@ -50,6 +51,7 @@
<el-form-item label="${comment}"> <el-form-item label="${comment}">
<el-date-picker <el-date-picker
v-model="daterange${AttrName}" v-model="daterange${AttrName}"
size="small"
style="width: 240px" style="width: 240px"
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd"
type="daterange" type="daterange"
@ -78,24 +80,14 @@
v-hasPermi="['${moduleName}:${businessName}:add']" v-hasPermi="['${moduleName}:${businessName}:add']"
>新增</el-button> >新增</el-button>
</el-col> </el-col>
<el-col :span="1.5">
<el-button
type="info"
plain
icon="el-icon-sort"
size="mini"
@click="toggleExpandAll"
>展开/折叠</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
<el-table <el-table
v-if="refreshTable"
v-loading="loading" v-loading="loading"
:data="${businessName}List" :data="${businessName}List"
row-key="${treeCode}" row-key="${treeCode}"
:default-expand-all="isExpandAll" default-expand-all
:tree-props="{children: 'children', hasChildren: 'hasChildren'}" :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
> >
#foreach($column in $columns) #foreach($column in $columns)
@ -113,12 +105,6 @@
<span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span> <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
</template> </template>
</el-table-column> </el-table-column>
#elseif($column.list && $column.htmlType == "imageUpload")
<el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
<template slot-scope="scope">
<image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
</template>
</el-table-column>
#elseif($column.list && "" != $column.dictType) #elseif($column.list && "" != $column.dictType)
<el-table-column label="${comment}" align="center" prop="${javaField}"> <el-table-column label="${comment}" align="center" prop="${javaField}">
<template slot-scope="scope"> <template slot-scope="scope">
@ -188,11 +174,11 @@
</el-form-item> </el-form-item>
#elseif($column.htmlType == "imageUpload") #elseif($column.htmlType == "imageUpload")
<el-form-item label="${comment}"> <el-form-item label="${comment}">
<image-upload v-model="form.${field}"/> <imageUpload v-model="form.${field}"/>
</el-form-item> </el-form-item>
#elseif($column.htmlType == "fileUpload") #elseif($column.htmlType == "fileUpload")
<el-form-item label="${comment}"> <el-form-item label="${comment}">
<file-upload v-model="form.${field}"/> <fileUpload v-model="form.${field}"/>
</el-form-item> </el-form-item>
#elseif($column.htmlType == "editor") #elseif($column.htmlType == "editor")
<el-form-item label="${comment}"> <el-form-item label="${comment}">
@ -252,7 +238,7 @@
</el-form-item> </el-form-item>
#elseif($column.htmlType == "datetime") #elseif($column.htmlType == "datetime")
<el-form-item label="${comment}" prop="${field}"> <el-form-item label="${comment}" prop="${field}">
<el-date-picker clearable <el-date-picker clearable size="small"
v-model="form.${field}" v-model="form.${field}"
type="date" type="date"
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd"
@ -303,10 +289,6 @@ export default {
title: "", title: "",
// 是否显示弹出层 // 是否显示弹出层
open: false, open: false,
// 是否展开,默认全部展开
isExpandAll: true,
// 重新渲染表格状态
refreshTable: true,
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
@ -437,14 +419,6 @@ export default {
this.open = true; this.open = true;
this.title = "添加${functionName}"; this.title = "添加${functionName}";
}, },
/** 展开/折叠操作 */
toggleExpandAll() {
this.refreshTable = false;
this.isExpandAll = !this.isExpandAll;
this.$nextTick(() => {
this.refreshTable = true;
});
},
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset(); this.reset();

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
#foreach($column in $columns) #foreach($column in $columns)
#if($column.query) #if($column.query)
#set($dictType=$column.dictType) #set($dictType=$column.dictType)
@ -17,12 +17,13 @@
v-model="queryParams.${column.javaField}" v-model="queryParams.${column.javaField}"
placeholder="请输入${comment}" placeholder="请输入${comment}"
clearable clearable
size="small"
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType) #elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
<el-form-item label="${comment}" prop="${column.javaField}"> <el-form-item label="${comment}" prop="${column.javaField}">
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable> <el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable size="small">
<el-option <el-option
v-for="dict in dict.type.${dictType}" v-for="dict in dict.type.${dictType}"
:key="dict.value" :key="dict.value"
@ -33,23 +34,24 @@
</el-form-item> </el-form-item>
#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType) #elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
<el-form-item label="${comment}" prop="${column.javaField}"> <el-form-item label="${comment}" prop="${column.javaField}">
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable> <el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable size="small">
<el-option label="请选择字典生成" value="" /> <el-option label="请选择字典生成" value="" />
</el-select> </el-select>
</el-form-item> </el-form-item>
#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN") #elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
<el-form-item label="${comment}" prop="${column.javaField}"> <el-form-item label="${comment}" prop="${column.javaField}">
<el-date-picker clearable <el-date-picker clearable size="small"
v-model="queryParams.${column.javaField}" v-model="queryParams.${column.javaField}"
type="date" type="date"
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd"
placeholder="选择${comment}"> placeholder="选择${comment}">
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
<el-form-item label="${comment}"> <el-form-item label="${comment}">
<el-date-picker <el-date-picker
v-model="daterange${AttrName}" v-model="daterange${AttrName}"
size="small"
style="width: 240px" style="width: 240px"
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd"
type="daterange" type="daterange"
@ -131,12 +133,6 @@
<span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span> <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
</template> </template>
</el-table-column> </el-table-column>
#elseif($column.list && $column.htmlType == "imageUpload")
<el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
<template slot-scope="scope">
<image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
</template>
</el-table-column>
#elseif($column.list && "" != $column.dictType) #elseif($column.list && "" != $column.dictType)
<el-table-column label="${comment}" align="center" prop="${javaField}"> <el-table-column label="${comment}" align="center" prop="${javaField}">
<template slot-scope="scope"> <template slot-scope="scope">
@ -199,11 +195,11 @@
</el-form-item> </el-form-item>
#elseif($column.htmlType == "imageUpload") #elseif($column.htmlType == "imageUpload")
<el-form-item label="${comment}"> <el-form-item label="${comment}">
<image-upload v-model="form.${field}"/> <imageUpload v-model="form.${field}"/>
</el-form-item> </el-form-item>
#elseif($column.htmlType == "fileUpload") #elseif($column.htmlType == "fileUpload")
<el-form-item label="${comment}"> <el-form-item label="${comment}">
<file-upload v-model="form.${field}"/> <fileUpload v-model="form.${field}"/>
</el-form-item> </el-form-item>
#elseif($column.htmlType == "editor") #elseif($column.htmlType == "editor")
<el-form-item label="${comment}"> <el-form-item label="${comment}">
@ -263,11 +259,11 @@
</el-form-item> </el-form-item>
#elseif($column.htmlType == "datetime") #elseif($column.htmlType == "datetime")
<el-form-item label="${comment}" prop="${field}"> <el-form-item label="${comment}" prop="${field}">
<el-date-picker clearable <el-date-picker clearable size="small"
v-model="form.${field}" v-model="form.${field}"
type="date" type="date"
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd"
placeholder="选择${comment}"> placeholder="选择${comment}">
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
#elseif($column.htmlType == "textarea") #elseif($column.htmlType == "textarea")
@ -300,39 +296,12 @@
#set($comment=$column.columnComment) #set($comment=$column.columnComment)
#end #end
#if($column.pk || $javaField == ${subTableFkclassName}) #if($column.pk || $javaField == ${subTableFkclassName})
#elseif($column.list && $column.htmlType == "input") #elseif($column.list && "" != $javaField)
<el-table-column label="$comment" prop="${javaField}" width="150"> <el-table-column label="$comment" prop="${javaField}">
<template slot-scope="scope"> <template slot-scope="scope">
<el-input v-model="scope.row.$javaField" placeholder="请输入$comment" /> <el-input v-model="scope.row.$javaField" placeholder="请输入$comment" />
</template> </template>
</el-table-column> </el-table-column>
#elseif($column.list && $column.htmlType == "datetime")
<el-table-column label="$comment" prop="${javaField}" width="240">
<template slot-scope="scope">
<el-date-picker clearable v-model="scope.row.$javaField" type="date" value-format="yyyy-MM-dd" placeholder="请选择$comment" />
</template>
</el-table-column>
#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" != $column.dictType)
<el-table-column label="$comment" prop="${javaField}" width="150">
<template slot-scope="scope">
<el-select v-model="scope.row.$javaField" placeholder="请选择$comment">
<el-option
v-for="dict in dict.type.$column.dictType"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</template>
</el-table-column>
#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" == $column.dictType)
<el-table-column label="$comment" prop="${javaField}" width="150">
<template slot-scope="scope">
<el-select v-model="scope.row.$javaField" placeholder="请选择$comment">
<el-option label="请选择字典生成" value="" />
</el-select>
</template>
</el-table-column>
#end #end
#end #end
</el-table> </el-table>

View File

@ -1,486 +0,0 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
#foreach($column in $columns)
#if($column.query)
#set($dictType=$column.dictType)
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set($parentheseIndex=$column.columnComment.indexOf(""))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
#if($column.htmlType == "input")
<el-form-item label="${comment}" prop="${column.javaField}">
<el-input
v-model="queryParams.${column.javaField}"
placeholder="请输入${comment}"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
<el-form-item label="${comment}" prop="${column.javaField}">
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
<el-option
v-for="dict in ${dictType}"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
<el-form-item label="${comment}" prop="${column.javaField}">
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
<el-form-item label="${comment}" prop="${column.javaField}">
<el-date-picker clearable
v-model="queryParams.${column.javaField}"
type="date"
value-format="YYYY-MM-DD"
placeholder="选择${comment}">
</el-date-picker>
</el-form-item>
#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
<el-form-item label="${comment}" style="width: 308px">
<el-date-picker
v-model="daterange${AttrName}"
value-format="YYYY-MM-DD"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
#end
#end
#end
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['${moduleName}:${businessName}:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="info"
plain
icon="Sort"
@click="toggleExpandAll"
>展开/折叠</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table
v-if="refreshTable"
v-loading="loading"
:data="${businessName}List"
row-key="${treeCode}"
:default-expand-all="isExpandAll"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
>
#foreach($column in $columns)
#set($javaField=$column.javaField)
#set($parentheseIndex=$column.columnComment.indexOf(""))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
#if($column.pk)
#elseif($column.list && $column.htmlType == "datetime")
<el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
#elseif($column.list && $column.htmlType == "imageUpload")
<el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
<template #default="scope">
<image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
</template>
</el-table-column>
#elseif($column.list && "" != $column.dictType)
<el-table-column label="${comment}" align="center" prop="${javaField}">
<template #default="scope">
#if($column.htmlType == "checkbox")
<dict-tag :options="${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
#else
<dict-tag :options="${column.dictType}" :value="scope.row.${javaField}"/>
#end
</template>
</el-table-column>
#elseif($column.list && "" != $javaField)
#if(${foreach.index} == 1)
<el-table-column label="${comment}" prop="${javaField}" />
#else
<el-table-column label="${comment}" align="center" prop="${javaField}" />
#end
#end
#end
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button
type="text"
icon="Edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['${moduleName}:${businessName}:edit']"
>修改</el-button>
<el-button
type="text"
icon="Plus"
@click="handleAdd(scope.row)"
v-hasPermi="['${moduleName}:${businessName}:add']"
>新增</el-button>
<el-button
type="text"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['${moduleName}:${businessName}:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 添加或修改${functionName}对话框 -->
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
<el-form ref="${businessName}Ref" :model="form" :rules="rules" label-width="80px">
#foreach($column in $columns)
#set($field=$column.javaField)
#if($column.insert && !$column.pk)
#if(($column.usableColumn) || (!$column.superColumn))
#set($parentheseIndex=$column.columnComment.indexOf(""))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
#set($dictType=$column.dictType)
#if("" != $treeParentCode && $column.javaField == $treeParentCode)
<el-form-item label="${comment}" prop="${treeParentCode}">
<el-tree-select
v-model="form.${treeParentCode}"
:data="${businessName}Options"
:props="{ value: '${treeCode}', label: '${treeName}', children: 'children' }"
value-key="${treeCode}"
placeholder="请选择${comment}"
check-strictly
/>
</el-form-item>
#elseif($column.htmlType == "input")
<el-form-item label="${comment}" prop="${field}">
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
</el-form-item>
#elseif($column.htmlType == "imageUpload")
<el-form-item label="${comment}">
<image-upload v-model="form.${field}"/>
</el-form-item>
#elseif($column.htmlType == "fileUpload")
<el-form-item label="${comment}">
<file-upload v-model="form.${field}"/>
</el-form-item>
#elseif($column.htmlType == "editor")
<el-form-item label="${comment}">
<editor v-model="form.${field}" :min-height="192"/>
</el-form-item>
#elseif($column.htmlType == "select" && "" != $dictType)
<el-form-item label="${comment}" prop="${field}">
<el-select v-model="form.${field}" placeholder="请选择${comment}">
<el-option
v-for="dict in ${dictType}"
:key="dict.value"
:label="dict.label"
#if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end
></el-option>
</el-select>
</el-form-item>
#elseif($column.htmlType == "select" && $dictType)
<el-form-item label="${comment}" prop="${field}">
<el-select v-model="form.${field}" placeholder="请选择${comment}">
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
#elseif($column.htmlType == "checkbox" && "" != $dictType)
<el-form-item label="${comment}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox
v-for="dict in ${dictType}"
:key="dict.value"
:label="dict.value">
{{dict.label}}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "checkbox" && $dictType)
<el-form-item label="${comment}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox>请选择字典生成</el-checkbox>
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio" && "" != $dictType)
<el-form-item label="${comment}">
<el-radio-group v-model="form.${field}">
<el-radio
v-for="dict in ${dictType}"
:key="dict.value"
#if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
#elseif($column.htmlType == "radio" && $dictType)
<el-form-item label="${comment}">
<el-radio-group v-model="form.${field}">
<el-radio label="1">请选择字典生成</el-radio>
</el-radio-group>
</el-form-item>
#elseif($column.htmlType == "datetime")
<el-form-item label="${comment}" prop="${field}">
<el-date-picker clearable
v-model="form.${field}"
type="date"
value-format="YYYY-MM-DD"
placeholder="选择${comment}">
</el-date-picker>
</el-form-item>
#elseif($column.htmlType == "textarea")
<el-form-item label="${comment}" prop="${field}">
<el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
</el-form-item>
#end
#end
#end
#end
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="${BusinessName}">
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
const { proxy } = getCurrentInstance();
#if(${dicts} != '')
#set($dictsNoSymbol=$dicts.replace("'", ""))
const { ${dictsNoSymbol} } = proxy.useDict(${dicts});
#end
const ${businessName}List = ref([]);
const ${businessName}Options = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const title = ref("");
const isExpandAll = ref(true);
const refreshTable = ref(true);
#foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
const daterange${AttrName} = ref([]);
#end
#end
const data = reactive({
form: {},
queryParams: {
#foreach ($column in $columns)
#if($column.query)
$column.javaField: null#if($foreach.count != $columns.size()),#end
#end
#end
},
rules: {
#foreach ($column in $columns)
#if($column.required)
#set($parentheseIndex=$column.columnComment.indexOf(""))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
$column.javaField: [
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
]#if($foreach.count != $columns.size()),#end
#end
#end
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询${functionName}列表 */
function getList() {
loading.value = true;
#foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
queryParams.value.params = {};
#break
#end
#end
#foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != daterange${AttrName} && '' != daterange${AttrName}) {
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0];
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1];
}
#end
#end
list${BusinessName}(queryParams.value).then(response => {
${businessName}List.value = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}");
loading.value = false;
});
}
/** 查询${functionName}下拉树结构 */
function getTreeselect() {
list${BusinessName}().then(response => {
${businessName}Options.value = [];
const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] };
data.children = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}");
${businessName}Options.value.push(data);
});
}
// 取消按钮
function cancel() {
open.value = false;
reset();
}
// 表单重置
function reset() {
form.value = {
#foreach ($column in $columns)
#if($column.htmlType == "radio")
$column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($foreach.count != $columns.size()),#end
#elseif($column.htmlType == "checkbox")
$column.javaField: []#if($foreach.count != $columns.size()),#end
#else
$column.javaField: null#if($foreach.count != $columns.size()),#end
#end
#end
};
proxy.resetForm("${businessName}Ref");
}
/** 搜索按钮操作 */
function handleQuery() {
getList();
}
/** 重置按钮操作 */
function resetQuery() {
#foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
daterange${AttrName}.value = [];
#end
#end
proxy.resetForm("queryRef");
handleQuery();
}
/** 新增按钮操作 */
function handleAdd(row) {
reset();
getTreeselect();
if (row != null && row.${treeCode}) {
form.value.${treeParentCode} = row.${treeCode};
} else {
form.value.${treeParentCode} = 0;
}
open.value = true;
title.value = "添加${functionName}";
}
/** 展开/折叠操作 */
function toggleExpandAll() {
refreshTable.value = false;
isExpandAll.value = !isExpandAll.value;
nextTick(() => {
refreshTable.value = true;
});
}
/** 修改按钮操作 */
async function handleUpdate(row) {
reset();
await getTreeselect();
if (row != null) {
form.value.${treeParentCode} = row.${treeCode};
}
get${BusinessName}(row.${pkColumn.javaField}).then(response => {
form.value = response.data;
#foreach ($column in $columns)
#if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.split(",");
#end
#end
open.value = true;
title.value = "修改${functionName}";
});
}
/** 提交按钮 */
function submitForm() {
proxy.#[[$]]#refs["${businessName}Ref"].validate(valid => {
if (valid) {
#foreach ($column in $columns)
#if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.join(",");
#end
#end
if (form.value.${pkColumn.javaField} != null) {
update${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("修改成功");
open.value = false;
getList();
});
} else {
add${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("新增成功");
open.value = false;
getList();
});
}
}
});
}
/** 删除按钮操作 */
function handleDelete(row) {
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() {
return del${BusinessName}(row.${pkColumn.javaField});
}).then(() => {
getList();
proxy.#[[$modal]]#.msgSuccess("删除成功");
}).catch(() => {});
}
getList();
</script>

View File

@ -1,596 +0,0 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
#foreach($column in $columns)
#if($column.query)
#set($dictType=$column.dictType)
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set($parentheseIndex=$column.columnComment.indexOf(""))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
#if($column.htmlType == "input")
<el-form-item label="${comment}" prop="${column.javaField}">
<el-input
v-model="queryParams.${column.javaField}"
placeholder="请输入${comment}"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
<el-form-item label="${comment}" prop="${column.javaField}">
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
<el-option
v-for="dict in ${dictType}"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
<el-form-item label="${comment}" prop="${column.javaField}">
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
<el-form-item label="${comment}" prop="${column.javaField}">
<el-date-picker clearable
v-model="queryParams.${column.javaField}"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择${comment}">
</el-date-picker>
</el-form-item>
#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
<el-form-item label="${comment}" style="width: 308px">
<el-date-picker
v-model="daterange${AttrName}"
value-format="YYYY-MM-DD"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
#end
#end
#end
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['${moduleName}:${businessName}:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['${moduleName}:${businessName}:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['${moduleName}:${businessName}:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['${moduleName}:${businessName}:export']"
>导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="${businessName}List" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
#foreach($column in $columns)
#set($javaField=$column.javaField)
#set($parentheseIndex=$column.columnComment.indexOf(""))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
#if($column.pk)
<el-table-column label="${comment}" align="center" prop="${javaField}" />
#elseif($column.list && $column.htmlType == "datetime")
<el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
#elseif($column.list && $column.htmlType == "imageUpload")
<el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
<template #default="scope">
<image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
</template>
</el-table-column>
#elseif($column.list && "" != $column.dictType)
<el-table-column label="${comment}" align="center" prop="${javaField}">
<template #default="scope">
#if($column.htmlType == "checkbox")
<dict-tag :options="${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
#else
<dict-tag :options="${column.dictType}" :value="scope.row.${javaField}"/>
#end
</template>
</el-table-column>
#elseif($column.list && "" != $javaField)
<el-table-column label="${comment}" align="center" prop="${javaField}" />
#end
#end
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button
type="text"
icon="Edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['${moduleName}:${businessName}:edit']"
>修改</el-button>
<el-button
type="text"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['${moduleName}:${businessName}:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改${functionName}对话框 -->
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
<el-form ref="${businessName}Ref" :model="form" :rules="rules" label-width="80px">
#foreach($column in $columns)
#set($field=$column.javaField)
#if($column.insert && !$column.pk)
#if(($column.usableColumn) || (!$column.superColumn))
#set($parentheseIndex=$column.columnComment.indexOf(""))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
#set($dictType=$column.dictType)
#if($column.htmlType == "input")
<el-form-item label="${comment}" prop="${field}">
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
</el-form-item>
#elseif($column.htmlType == "imageUpload")
<el-form-item label="${comment}">
<image-upload v-model="form.${field}"/>
</el-form-item>
#elseif($column.htmlType == "fileUpload")
<el-form-item label="${comment}">
<file-upload v-model="form.${field}"/>
</el-form-item>
#elseif($column.htmlType == "editor")
<el-form-item label="${comment}">
<editor v-model="form.${field}" :min-height="192"/>
</el-form-item>
#elseif($column.htmlType == "select" && "" != $dictType)
<el-form-item label="${comment}" prop="${field}">
<el-select v-model="form.${field}" placeholder="请选择${comment}">
<el-option
v-for="dict in ${dictType}"
:key="dict.value"
:label="dict.label"
#if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end
></el-option>
</el-select>
</el-form-item>
#elseif($column.htmlType == "select" && $dictType)
<el-form-item label="${comment}" prop="${field}">
<el-select v-model="form.${field}" placeholder="请选择${comment}">
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
#elseif($column.htmlType == "checkbox" && "" != $dictType)
<el-form-item label="${comment}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox
v-for="dict in ${dictType}"
:key="dict.value"
:label="dict.value">
{{dict.label}}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "checkbox" && $dictType)
<el-form-item label="${comment}">
<el-checkbox-group v-model="form.${field}">
<el-checkbox>请选择字典生成</el-checkbox>
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio" && "" != $dictType)
<el-form-item label="${comment}">
<el-radio-group v-model="form.${field}">
<el-radio
v-for="dict in ${dictType}"
:key="dict.value"
#if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
#elseif($column.htmlType == "radio" && $dictType)
<el-form-item label="${comment}">
<el-radio-group v-model="form.${field}">
<el-radio label="1">请选择字典生成</el-radio>
</el-radio-group>
</el-form-item>
#elseif($column.htmlType == "datetime")
<el-form-item label="${comment}" prop="${field}">
<el-date-picker clearable
v-model="form.${field}"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择${comment}">
</el-date-picker>
</el-form-item>
#elseif($column.htmlType == "textarea")
<el-form-item label="${comment}" prop="${field}">
<el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
</el-form-item>
#end
#end
#end
#end
#if($table.sub)
<el-divider content-position="center">${subTable.functionName}信息</el-divider>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" icon="Plus" @click="handleAdd${subClassName}">添加</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" icon="Delete" @click="handleDelete${subClassName}">删除</el-button>
</el-col>
</el-row>
<el-table :data="${subclassName}List" :row-class-name="row${subClassName}Index" @selection-change="handle${subClassName}SelectionChange" ref="${subclassName}">
<el-table-column type="selection" width="50" align="center" />
<el-table-column label="序号" align="center" prop="index" width="50"/>
#foreach($column in $subTable.columns)
#set($javaField=$column.javaField)
#set($parentheseIndex=$column.columnComment.indexOf(""))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
#if($column.pk || $javaField == ${subTableFkclassName})
#elseif($column.list && $column.htmlType == "input")
<el-table-column label="$comment" prop="${javaField}" width="150">
<template #default="scope">
<el-input v-model="scope.row.$javaField" placeholder="请输入$comment" />
</template>
</el-table-column>
#elseif($column.list && $column.htmlType == "datetime")
<el-table-column label="$comment" prop="${javaField}" width="240">
<template #default="scope">
<el-date-picker clearable
v-model="scope.row.$javaField"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择$comment">
</el-date-picker>
</template>
</el-table-column>
#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" != $column.dictType)
<el-table-column label="$comment" prop="${javaField}" width="150">
<template #default="scope">
<el-select v-model="scope.row.$javaField" placeholder="请选择$comment">
<el-option
v-for="dict in $column.dictType"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</template>
</el-table-column>
#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" == $column.dictType)
<el-table-column label="$comment" prop="${javaField}" width="150">
<template #default="scope">
<el-select v-model="scope.row.$javaField" placeholder="请选择$comment">
<el-option label="请选择字典生成" value="" />
</el-select>
</template>
</el-table-column>
#end
#end
</el-table>
#end
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="${BusinessName}">
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
const { proxy } = getCurrentInstance();
#if(${dicts} != '')
#set($dictsNoSymbol=$dicts.replace("'", ""))
const { ${dictsNoSymbol} } = proxy.useDict(${dicts});
#end
const ${businessName}List = ref([]);
#if($table.sub)
const ${subclassName}List = ref([]);
#end
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
#if($table.sub)
const checked${subClassName} = ref([]);
#end
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");
#foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
const daterange${AttrName} = ref([]);
#end
#end
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
#foreach ($column in $columns)
#if($column.query)
$column.javaField: null#if($foreach.count != $columns.size()),#end
#end
#end
},
rules: {
#foreach ($column in $columns)
#if($column.required)
#set($parentheseIndex=$column.columnComment.indexOf(""))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
$column.javaField: [
{ required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
]#if($foreach.count != $columns.size()),#end
#end
#end
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询${functionName}列表 */
function getList() {
loading.value = true;
#foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
queryParams.value.params = {};
#break
#end
#end
#foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != daterange${AttrName} && '' != daterange${AttrName}) {
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0];
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1];
}
#end
#end
list${BusinessName}(queryParams.value).then(response => {
${businessName}List.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
// 取消按钮
function cancel() {
open.value = false;
reset();
}
// 表单重置
function reset() {
form.value = {
#foreach ($column in $columns)
#if($column.htmlType == "radio")
$column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($foreach.count != $columns.size()),#end
#elseif($column.htmlType == "checkbox")
$column.javaField: []#if($foreach.count != $columns.size()),#end
#else
$column.javaField: null#if($foreach.count != $columns.size()),#end
#end
#end
};
#if($table.sub)
${subclassName}List.value = [];
#end
proxy.resetForm("${businessName}Ref");
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
/** 重置按钮操作 */
function resetQuery() {
#foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
daterange${AttrName}.value = [];
#end
#end
proxy.resetForm("queryRef");
handleQuery();
}
// 多选框选中数据
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.${pkColumn.javaField});
single.value = selection.length != 1;
multiple.value = !selection.length;
}
/** 新增按钮操作 */
function handleAdd() {
reset();
open.value = true;
title.value = "添加${functionName}";
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset();
const ${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value
get${BusinessName}(${pkColumn.javaField}).then(response => {
form.value = response.data;
#foreach ($column in $columns)
#if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.split(",");
#end
#end
#if($table.sub)
${subclassName}List.value = response.data.${subclassName}List;
#end
open.value = true;
title.value = "修改${functionName}";
});
}
/** 提交按钮 */
function submitForm() {
proxy.#[[$]]#refs["${businessName}Ref"].validate(valid => {
if (valid) {
#foreach ($column in $columns)
#if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.join(",");
#end
#end
#if($table.sub)
form.value.${subclassName}List = ${subclassName}List.value;
#end
if (form.value.${pkColumn.javaField} != null) {
update${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("修改成功");
open.value = false;
getList();
});
} else {
add${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("新增成功");
open.value = false;
getList();
});
}
}
});
}
/** 删除按钮操作 */
function handleDelete(row) {
const ${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value;
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?').then(function() {
return del${BusinessName}(${pkColumn.javaField}s);
}).then(() => {
getList();
proxy.#[[$modal]]#.msgSuccess("删除成功");
}).catch(() => {});
}
#if($table.sub)
/** ${subTable.functionName}序号 */
function row${subClassName}Index({ row, rowIndex }) {
row.index = rowIndex + 1;
}
/** ${subTable.functionName}添加按钮操作 */
function handleAdd${subClassName}() {
let obj = {};
#foreach($column in $subTable.columns)
#if($column.pk || $column.javaField == ${subTableFkclassName})
#elseif($column.list && "" != $javaField)
obj.$column.javaField = "";
#end
#end
${subclassName}List.value.push(obj);
}
/** ${subTable.functionName}删除按钮操作 */
function handleDelete${subClassName}() {
if (checked${subClassName}.value.length == 0) {
proxy.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据");
} else {
const ${subclassName}s = ${subclassName}List.value;
const checked${subClassName}s = checked${subClassName}.value;
${subclassName}List.value = ${subclassName}s.filter(function(item) {
return checked${subClassName}s.indexOf(item.index) == -1
});
}
}
/** 复选框选中数据 */
function handle${subClassName}SelectionChange(selection) {
checked${subClassName}.value = selection.map(item => item.index)
}
#end
/** 导出按钮操作 */
function handleExport() {
proxy.download('${moduleName}/${businessName}/export', {
...queryParams.value
}, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
}
getList();
</script>

View File

@ -1 +0,0 @@
如果使用的是RuoYi-Vue3前端那么需要覆盖一下此目录的模板index.vue.vm、index-tree.vue.vm文件到上级vue目录。

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.8.2</version> <version>3.8.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -1,57 +1,57 @@
//package com.ruoyi.quartz.config; package com.ruoyi.quartz.config;
//
//import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
//import org.springframework.scheduling.quartz.SchedulerFactoryBean; import org.springframework.scheduling.quartz.SchedulerFactoryBean;
//import javax.sql.DataSource; import javax.sql.DataSource;
//import java.util.Properties; import java.util.Properties;
//
///** /**
// * 定时任务配置单机部署建议删除此类和qrtz数据库表默认走内存会最高效 * 定时任务配置单机部署建议删除此类和qrtz数据库表默认走内存会最高效
// * *
// * @author ruoyi * @author ruoyi
// */ */
//@Configuration @Configuration
//public class ScheduleConfig public class ScheduleConfig
//{ {
// @Bean @Bean
// public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource)
// { {
// SchedulerFactoryBean factory = new SchedulerFactoryBean(); SchedulerFactoryBean factory = new SchedulerFactoryBean();
// factory.setDataSource(dataSource); factory.setDataSource(dataSource);
//
// // quartz参数 // quartz参数
// Properties prop = new Properties(); Properties prop = new Properties();
// prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler"); prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler");
// prop.put("org.quartz.scheduler.instanceId", "AUTO"); prop.put("org.quartz.scheduler.instanceId", "AUTO");
// // 线程池配置 // 线程池配置
// prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool"); prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
// prop.put("org.quartz.threadPool.threadCount", "20"); prop.put("org.quartz.threadPool.threadCount", "20");
// prop.put("org.quartz.threadPool.threadPriority", "5"); prop.put("org.quartz.threadPool.threadPriority", "5");
// // JobStore配置 // JobStore配置
// prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore"); prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
// // 集群配置 // 集群配置
// prop.put("org.quartz.jobStore.isClustered", "true"); prop.put("org.quartz.jobStore.isClustered", "true");
// prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000"); prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
// prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1"); prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
// prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true"); prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
//
// // sqlserver 启用 // sqlserver 启用
// // prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?"); // prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
// prop.put("org.quartz.jobStore.misfireThreshold", "12000"); prop.put("org.quartz.jobStore.misfireThreshold", "12000");
// prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_"); prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
// factory.setQuartzProperties(prop); factory.setQuartzProperties(prop);
//
// factory.setSchedulerName("RuoyiScheduler"); factory.setSchedulerName("RuoyiScheduler");
// // 延时启动 // 延时启动
// factory.setStartupDelay(1); factory.setStartupDelay(1);
// factory.setApplicationContextSchedulerContextKey("applicationContextKey"); factory.setApplicationContextSchedulerContextKey("applicationContextKey");
// // 可选QuartzScheduler // 可选QuartzScheduler
// // 启动时更新己存在的Job这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 // 启动时更新己存在的Job这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
// factory.setOverwriteExistingJobs(true); factory.setOverwriteExistingJobs(true);
// // 设置自动启动默认为true // 设置自动启动默认为true
// factory.setAutoStartup(true); factory.setAutoStartup(true);
//
// return factory; return factory;
// } }
//} }

View File

@ -25,7 +25,6 @@ import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.quartz.domain.SysJob; import com.ruoyi.quartz.domain.SysJob;
import com.ruoyi.quartz.service.ISysJobService; import com.ruoyi.quartz.service.ISysJobService;
import com.ruoyi.quartz.util.CronUtils; import com.ruoyi.quartz.util.CronUtils;
import com.ruoyi.quartz.util.ScheduleUtils;
/** /**
* 调度任务信息操作处理 * 调度任务信息操作处理
@ -88,24 +87,20 @@ public class SysJobController extends BaseController
} }
else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI)) else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
{ {
return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi'调用"); return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
} }
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS })) else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_LDAP))
{ {
return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap(s)'调用"); return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap://'调用");
} }
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS })) else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
{ {
return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)'调用"); return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用");
} }
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR)) else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
{ {
return error("新增任务'" + job.getJobName() + "'失败,目标字符串存在违规"); return error("新增任务'" + job.getJobName() + "'失败,目标字符串存在违规");
} }
else if (!ScheduleUtils.whiteList(job.getInvokeTarget()))
{
return error("新增任务'" + job.getJobName() + "'失败,目标字符串不在白名单内");
}
job.setCreateBy(getUsername()); job.setCreateBy(getUsername());
return toAjax(jobService.insertJob(job)); return toAjax(jobService.insertJob(job));
} }
@ -124,24 +119,20 @@ public class SysJobController extends BaseController
} }
else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI)) else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
{ {
return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi'调用"); return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
} }
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS })) else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_LDAP))
{ {
return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap(s)'调用"); return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap://'调用");
} }
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS })) else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
{ {
return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)'调用"); return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用");
} }
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR)) else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
{ {
return error("修改任务'" + job.getJobName() + "'失败,目标字符串存在违规"); return error("修改任务'" + job.getJobName() + "'失败,目标字符串存在违规");
} }
else if (!ScheduleUtils.whiteList(job.getInvokeTarget()))
{
return error("修改任务'" + job.getJobName() + "'失败,目标字符串不在白名单内");
}
job.setUpdateBy(getUsername()); job.setUpdateBy(getUsername());
return toAjax(jobService.updateJob(job)); return toAjax(jobService.updateJob(job));
} }

View File

@ -65,7 +65,7 @@ public class JobInvokeUtil
/** /**
* 校验是否为为class包名 * 校验是否为为class包名
* *
* @param invokeTarget 名称 * @param str 名称
* @return true是 false否 * @return true是 false否
*/ */
public static boolean isValidClassName(String invokeTarget) public static boolean isValidClassName(String invokeTarget)
@ -110,30 +110,30 @@ public class JobInvokeUtil
{ {
return null; return null;
} }
String[] methodParams = methodStr.split(",(?=([^\"']*[\"'][^\"']*[\"'])*[^\"']*$)"); String[] methodParams = methodStr.split(",(?=(?:[^\']*\"[^\']*\')*[^\']*$)");
List<Object[]> classs = new LinkedList<>(); List<Object[]> classs = new LinkedList<>();
for (int i = 0; i < methodParams.length; i++) for (int i = 0; i < methodParams.length; i++)
{ {
String str = StringUtils.trimToEmpty(methodParams[i]); String str = StringUtils.trimToEmpty(methodParams[i]);
// String字符串类型'"开头 // String字符串类型包含'
if (StringUtils.startsWithAny(str, "'", "\"")) if (StringUtils.contains(str, "'"))
{ {
classs.add(new Object[] { StringUtils.substring(str, 1, str.length() - 1), String.class }); classs.add(new Object[] { StringUtils.replace(str, "'", ""), String.class });
} }
// boolean布尔类型等于true或者false // boolean布尔类型等于true或者false
else if ("true".equalsIgnoreCase(str) || "false".equalsIgnoreCase(str)) else if (StringUtils.equals(str, "true") || StringUtils.equalsIgnoreCase(str, "false"))
{ {
classs.add(new Object[] { Boolean.valueOf(str), Boolean.class }); classs.add(new Object[] { Boolean.valueOf(str), Boolean.class });
} }
// long长整形以L结尾 // long长整形包含L
else if (StringUtils.endsWith(str, "L")) else if (StringUtils.containsIgnoreCase(str, "L"))
{ {
classs.add(new Object[] { Long.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Long.class }); classs.add(new Object[] { Long.valueOf(StringUtils.replaceIgnoreCase(str, "L", "")), Long.class });
} }
// double浮点类型以D结尾 // double浮点类型包含D
else if (StringUtils.endsWith(str, "D")) else if (StringUtils.containsIgnoreCase(str, "D"))
{ {
classs.add(new Object[] { Double.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Double.class }); classs.add(new Object[] { Double.valueOf(StringUtils.replaceIgnoreCase(str, "D", "")), Double.class });
} }
// 其他类型归类为整形 // 其他类型归类为整形
else else

View File

@ -10,12 +10,9 @@ import org.quartz.Scheduler;
import org.quartz.SchedulerException; import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder; import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey; import org.quartz.TriggerKey;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.ScheduleConstants; import com.ruoyi.common.constant.ScheduleConstants;
import com.ruoyi.common.exception.job.TaskException; import com.ruoyi.common.exception.job.TaskException;
import com.ruoyi.common.exception.job.TaskException.Code; import com.ruoyi.common.exception.job.TaskException.Code;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.quartz.domain.SysJob; import com.ruoyi.quartz.domain.SysJob;
/** /**
@ -113,22 +110,4 @@ public class ScheduleUtils
+ "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR); + "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR);
} }
} }
/**
* 检查包名是否为白名单配置
*
* @param invokeTarget 目标字符串
* @return 结果
*/
public static boolean whiteList(String invokeTarget)
{
String packageName = StringUtils.substringBefore(invokeTarget, "(");
int count = StringUtils.countMatches(packageName, ".");
if (count > 1)
{
return StringUtils.containsAnyIgnoreCase(invokeTarget, Constants.JOB_WHITELIST_STR);
}
Object obj = SpringUtils.getBean(StringUtils.split(invokeTarget, ".")[0]);
return StringUtils.containsAnyIgnoreCase(obj.getClass().getPackage().getName(), Constants.JOB_WHITELIST_STR);
}
} }

View File

@ -86,7 +86,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="jobMessage != null and jobMessage != ''">#{jobMessage},</if> <if test="jobMessage != null and jobMessage != ''">#{jobMessage},</if>
<if test="status != null and status != ''">#{status},</if> <if test="status != null and status != ''">#{status},</if>
<if test="exceptionInfo != null and exceptionInfo != ''">#{exceptionInfo},</if> <if test="exceptionInfo != null and exceptionInfo != ''">#{exceptionInfo},</if>
current_timestamp sysdate()
) )
</insert> </insert>

View File

@ -75,7 +75,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="status !=null">status = #{status},</if> <if test="status !=null">status = #{status},</if>
<if test="remark != null and remark != ''">remark = #{remark},</if> <if test="remark != null and remark != ''">remark = #{remark},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if> <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
update_time = current_timestamp update_time = sysdate()
</set> </set>
where job_id = #{jobId} where job_id = #{jobId}
</update> </update>
@ -104,7 +104,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="status != null and status != ''">#{status},</if> <if test="status != null and status != ''">#{status},</if>
<if test="remark != null and remark != ''">#{remark},</if> <if test="remark != null and remark != ''">#{remark},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if> <if test="createBy != null and createBy != ''">#{createBy},</if>
current_timestamp sysdate()
) )
</insert> </insert>

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