parent
54b82058a9
commit
79697e1cb8
62 changed files with 4853 additions and 21 deletions
@ -1,25 +1,33 @@ |
||||
# ---> Java |
||||
# Compiled class file |
||||
*.class |
||||
HELP.md |
||||
target/ |
||||
!.mvn/wrapper/maven-wrapper.jar |
||||
!**/src/main/**/target/ |
||||
!**/src/test/**/target/ |
||||
|
||||
# Log file |
||||
*.log |
||||
### STS ### |
||||
.apt_generated |
||||
.classpath |
||||
.factorypath |
||||
.project |
||||
.settings |
||||
.springBeans |
||||
.sts4-cache |
||||
|
||||
# BlueJ files |
||||
*.ctxt |
||||
### IntelliJ IDEA ### |
||||
.idea |
||||
*.iws |
||||
*.iml |
||||
*.ipr |
||||
|
||||
# Mobile Tools for Java (J2ME) |
||||
.mtj.tmp/ |
||||
|
||||
# Package Files # |
||||
*.jar |
||||
*.war |
||||
*.nar |
||||
*.ear |
||||
*.zip |
||||
*.tar.gz |
||||
*.rar |
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml |
||||
hs_err_pid* |
||||
### NetBeans ### |
||||
/nbproject/private/ |
||||
/nbbuild/ |
||||
/dist/ |
||||
/nbdist/ |
||||
/.nb-gradle/ |
||||
build/ |
||||
!**/src/main/**/build/ |
||||
!**/src/test/**/build/ |
||||
|
||||
### VS Code ### |
||||
.vscode/ |
||||
|
@ -0,0 +1,118 @@ |
||||
/* |
||||
* Copyright 2007-present the original author or authors. |
||||
* |
||||
* Licensed 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. |
||||
*/ |
||||
|
||||
import java.net.*; |
||||
import java.io.*; |
||||
import java.nio.channels.*; |
||||
import java.util.Properties; |
||||
|
||||
public class MavenWrapperDownloader { |
||||
|
||||
private static final String WRAPPER_VERSION = "0.5.6"; |
||||
/** |
||||
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. |
||||
*/ |
||||
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" |
||||
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; |
||||
|
||||
/** |
||||
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to |
||||
* use instead of the default one. |
||||
*/ |
||||
private static final String MAVEN_WRAPPER_PROPERTIES_PATH = |
||||
".mvn/wrapper/maven-wrapper.properties"; |
||||
|
||||
/** |
||||
* Path where the maven-wrapper.jar will be saved to. |
||||
*/ |
||||
private static final String MAVEN_WRAPPER_JAR_PATH = |
||||
".mvn/wrapper/maven-wrapper.jar"; |
||||
|
||||
/** |
||||
* Name of the property which should be used to override the default download url for the wrapper. |
||||
*/ |
||||
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; |
||||
|
||||
public static void main(String args[]) { |
||||
System.out.println("- Downloader started"); |
||||
File baseDirectory = new File(args[0]); |
||||
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); |
||||
|
||||
// If the maven-wrapper.properties exists, read it and check if it contains a custom
|
||||
// wrapperUrl parameter.
|
||||
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); |
||||
String url = DEFAULT_DOWNLOAD_URL; |
||||
if (mavenWrapperPropertyFile.exists()) { |
||||
FileInputStream mavenWrapperPropertyFileInputStream = null; |
||||
try { |
||||
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); |
||||
Properties mavenWrapperProperties = new Properties(); |
||||
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); |
||||
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); |
||||
} catch (IOException e) { |
||||
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); |
||||
} finally { |
||||
try { |
||||
if (mavenWrapperPropertyFileInputStream != null) { |
||||
mavenWrapperPropertyFileInputStream.close(); |
||||
} |
||||
} catch (IOException e) { |
||||
// Ignore ...
|
||||
} |
||||
} |
||||
} |
||||
System.out.println("- Downloading from: " + url); |
||||
|
||||
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); |
||||
if (!outputFile.getParentFile().exists()) { |
||||
if (!outputFile.getParentFile().mkdirs()) { |
||||
System.out.println( |
||||
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); |
||||
} |
||||
} |
||||
System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); |
||||
try { |
||||
downloadFileFromURL(url, outputFile); |
||||
System.out.println("Done"); |
||||
System.exit(0); |
||||
} catch (Throwable e) { |
||||
System.out.println("- Error downloading"); |
||||
e.printStackTrace(); |
||||
System.exit(1); |
||||
} |
||||
} |
||||
|
||||
private static void downloadFileFromURL(String urlString, File destination) throws Exception { |
||||
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { |
||||
String username = System.getenv("MVNW_USERNAME"); |
||||
char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); |
||||
Authenticator.setDefault(new Authenticator() { |
||||
@Override |
||||
protected PasswordAuthentication getPasswordAuthentication() { |
||||
return new PasswordAuthentication(username, password); |
||||
} |
||||
}); |
||||
} |
||||
URL website = new URL(urlString); |
||||
ReadableByteChannel rbc; |
||||
rbc = Channels.newChannel(website.openStream()); |
||||
FileOutputStream fos = new FileOutputStream(destination); |
||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); |
||||
fos.close(); |
||||
rbc.close(); |
||||
} |
||||
|
||||
} |
Binary file not shown.
@ -0,0 +1,2 @@ |
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip |
||||
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar |
@ -0,0 +1,310 @@ |
||||
#!/bin/sh |
||||
# ---------------------------------------------------------------------------- |
||||
# Licensed to the Apache Software Foundation (ASF) under one |
||||
# or more contributor license agreements. See the NOTICE file |
||||
# distributed with this work for additional information |
||||
# regarding copyright ownership. The ASF licenses this file |
||||
# to you under the Apache License, Version 2.0 (the |
||||
# "License"); you may not use this file except in compliance |
||||
# with the License. You may obtain a copy of the License at |
||||
# |
||||
# https://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, |
||||
# software distributed under the License is distributed on an |
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||||
# KIND, either express or implied. See the License for the |
||||
# specific language governing permissions and limitations |
||||
# under the License. |
||||
# ---------------------------------------------------------------------------- |
||||
|
||||
# ---------------------------------------------------------------------------- |
||||
# Maven Start Up Batch script |
||||
# |
||||
# Required ENV vars: |
||||
# ------------------ |
||||
# JAVA_HOME - location of a JDK home dir |
||||
# |
||||
# Optional ENV vars |
||||
# ----------------- |
||||
# M2_HOME - location of maven2's installed home dir |
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven |
||||
# e.g. to debug Maven itself, use |
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 |
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files |
||||
# ---------------------------------------------------------------------------- |
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ] ; then |
||||
|
||||
if [ -f /etc/mavenrc ] ; then |
||||
. /etc/mavenrc |
||||
fi |
||||
|
||||
if [ -f "$HOME/.mavenrc" ] ; then |
||||
. "$HOME/.mavenrc" |
||||
fi |
||||
|
||||
fi |
||||
|
||||
# OS specific support. $var _must_ be set to either true or false. |
||||
cygwin=false; |
||||
darwin=false; |
||||
mingw=false |
||||
case "`uname`" in |
||||
CYGWIN*) cygwin=true ;; |
||||
MINGW*) mingw=true;; |
||||
Darwin*) darwin=true |
||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home |
||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html |
||||
if [ -z "$JAVA_HOME" ]; then |
||||
if [ -x "/usr/libexec/java_home" ]; then |
||||
export JAVA_HOME="`/usr/libexec/java_home`" |
||||
else |
||||
export JAVA_HOME="/Library/Java/Home" |
||||
fi |
||||
fi |
||||
;; |
||||
esac |
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then |
||||
if [ -r /etc/gentoo-release ] ; then |
||||
JAVA_HOME=`java-config --jre-home` |
||||
fi |
||||
fi |
||||
|
||||
if [ -z "$M2_HOME" ] ; then |
||||
## resolve links - $0 may be a link to maven's home |
||||
PRG="$0" |
||||
|
||||
# need this for relative symlinks |
||||
while [ -h "$PRG" ] ; do |
||||
ls=`ls -ld "$PRG"` |
||||
link=`expr "$ls" : '.*-> \(.*\)$'` |
||||
if expr "$link" : '/.*' > /dev/null; then |
||||
PRG="$link" |
||||
else |
||||
PRG="`dirname "$PRG"`/$link" |
||||
fi |
||||
done |
||||
|
||||
saveddir=`pwd` |
||||
|
||||
M2_HOME=`dirname "$PRG"`/.. |
||||
|
||||
# make it fully qualified |
||||
M2_HOME=`cd "$M2_HOME" && pwd` |
||||
|
||||
cd "$saveddir" |
||||
# echo Using m2 at $M2_HOME |
||||
fi |
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched |
||||
if $cygwin ; then |
||||
[ -n "$M2_HOME" ] && |
||||
M2_HOME=`cygpath --unix "$M2_HOME"` |
||||
[ -n "$JAVA_HOME" ] && |
||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"` |
||||
[ -n "$CLASSPATH" ] && |
||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"` |
||||
fi |
||||
|
||||
# For Mingw, ensure paths are in UNIX format before anything is touched |
||||
if $mingw ; then |
||||
[ -n "$M2_HOME" ] && |
||||
M2_HOME="`(cd "$M2_HOME"; pwd)`" |
||||
[ -n "$JAVA_HOME" ] && |
||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" |
||||
fi |
||||
|
||||
if [ -z "$JAVA_HOME" ]; then |
||||
javaExecutable="`which javac`" |
||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then |
||||
# readlink(1) is not available as standard on Solaris 10. |
||||
readLink=`which readlink` |
||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then |
||||
if $darwin ; then |
||||
javaHome="`dirname \"$javaExecutable\"`" |
||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" |
||||
else |
||||
javaExecutable="`readlink -f \"$javaExecutable\"`" |
||||
fi |
||||
javaHome="`dirname \"$javaExecutable\"`" |
||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'` |
||||
JAVA_HOME="$javaHome" |
||||
export JAVA_HOME |
||||
fi |
||||
fi |
||||
fi |
||||
|
||||
if [ -z "$JAVACMD" ] ; then |
||||
if [ -n "$JAVA_HOME" ] ; then |
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then |
||||
# IBM's JDK on AIX uses strange locations for the executables |
||||
JAVACMD="$JAVA_HOME/jre/sh/java" |
||||
else |
||||
JAVACMD="$JAVA_HOME/bin/java" |
||||
fi |
||||
else |
||||
JAVACMD="`which java`" |
||||
fi |
||||
fi |
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then |
||||
echo "Error: JAVA_HOME is not defined correctly." >&2 |
||||
echo " We cannot execute $JAVACMD" >&2 |
||||
exit 1 |
||||
fi |
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then |
||||
echo "Warning: JAVA_HOME environment variable is not set." |
||||
fi |
||||
|
||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher |
||||
|
||||
# traverses directory structure from process work directory to filesystem root |
||||
# first directory with .mvn subdirectory is considered project base directory |
||||
find_maven_basedir() { |
||||
|
||||
if [ -z "$1" ] |
||||
then |
||||
echo "Path not specified to find_maven_basedir" |
||||
return 1 |
||||
fi |
||||
|
||||
basedir="$1" |
||||
wdir="$1" |
||||
while [ "$wdir" != '/' ] ; do |
||||
if [ -d "$wdir"/.mvn ] ; then |
||||
basedir=$wdir |
||||
break |
||||
fi |
||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc) |
||||
if [ -d "${wdir}" ]; then |
||||
wdir=`cd "$wdir/.."; pwd` |
||||
fi |
||||
# end of workaround |
||||
done |
||||
echo "${basedir}" |
||||
} |
||||
|
||||
# concatenates all lines of a file |
||||
concat_lines() { |
||||
if [ -f "$1" ]; then |
||||
echo "$(tr -s '\n' ' ' < "$1")" |
||||
fi |
||||
} |
||||
|
||||
BASE_DIR=`find_maven_basedir "$(pwd)"` |
||||
if [ -z "$BASE_DIR" ]; then |
||||
exit 1; |
||||
fi |
||||
|
||||
########################################################################################## |
||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central |
||||
# This allows using the maven wrapper in projects that prohibit checking in binary data. |
||||
########################################################################################## |
||||
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo "Found .mvn/wrapper/maven-wrapper.jar" |
||||
fi |
||||
else |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." |
||||
fi |
||||
if [ -n "$MVNW_REPOURL" ]; then |
||||
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" |
||||
else |
||||
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" |
||||
fi |
||||
while IFS="=" read key value; do |
||||
case "$key" in (wrapperUrl) jarUrl="$value"; break ;; |
||||
esac |
||||
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo "Downloading from: $jarUrl" |
||||
fi |
||||
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" |
||||
if $cygwin; then |
||||
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` |
||||
fi |
||||
|
||||
if command -v wget > /dev/null; then |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo "Found wget ... using wget" |
||||
fi |
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then |
||||
wget "$jarUrl" -O "$wrapperJarPath" |
||||
else |
||||
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" |
||||
fi |
||||
elif command -v curl > /dev/null; then |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo "Found curl ... using curl" |
||||
fi |
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then |
||||
curl -o "$wrapperJarPath" "$jarUrl" -f |
||||
else |
||||
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f |
||||
fi |
||||
|
||||
else |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo "Falling back to using Java to download" |
||||
fi |
||||
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" |
||||
# For Cygwin, switch paths to Windows format before running javac |
||||
if $cygwin; then |
||||
javaClass=`cygpath --path --windows "$javaClass"` |
||||
fi |
||||
if [ -e "$javaClass" ]; then |
||||
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo " - Compiling MavenWrapperDownloader.java ..." |
||||
fi |
||||
# Compiling the Java class |
||||
("$JAVA_HOME/bin/javac" "$javaClass") |
||||
fi |
||||
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then |
||||
# Running the downloader |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo " - Running MavenWrapperDownloader.java ..." |
||||
fi |
||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") |
||||
fi |
||||
fi |
||||
fi |
||||
fi |
||||
########################################################################################## |
||||
# End of extension |
||||
########################################################################################## |
||||
|
||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo $MAVEN_PROJECTBASEDIR |
||||
fi |
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" |
||||
|
||||
# For Cygwin, switch paths to Windows format before running java |
||||
if $cygwin; then |
||||
[ -n "$M2_HOME" ] && |
||||
M2_HOME=`cygpath --path --windows "$M2_HOME"` |
||||
[ -n "$JAVA_HOME" ] && |
||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` |
||||
[ -n "$CLASSPATH" ] && |
||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"` |
||||
[ -n "$MAVEN_PROJECTBASEDIR" ] && |
||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` |
||||
fi |
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will |
||||
# work with both Windows and non-Windows executions. |
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" |
||||
export MAVEN_CMD_LINE_ARGS |
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain |
||||
|
||||
exec "$JAVACMD" \ |
||||
$MAVEN_OPTS \ |
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ |
||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ |
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" |
@ -0,0 +1,182 @@ |
||||
@REM ---------------------------------------------------------------------------- |
||||
@REM Licensed to the Apache Software Foundation (ASF) under one |
||||
@REM or more contributor license agreements. See the NOTICE file |
||||
@REM distributed with this work for additional information |
||||
@REM regarding copyright ownership. The ASF licenses this file |
||||
@REM to you under the Apache License, Version 2.0 (the |
||||
@REM "License"); you may not use this file except in compliance |
||||
@REM with the License. You may obtain a copy of the License at |
||||
@REM |
||||
@REM https://www.apache.org/licenses/LICENSE-2.0 |
||||
@REM |
||||
@REM Unless required by applicable law or agreed to in writing, |
||||
@REM software distributed under the License is distributed on an |
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||||
@REM KIND, either express or implied. See the License for the |
||||
@REM specific language governing permissions and limitations |
||||
@REM under the License. |
||||
@REM ---------------------------------------------------------------------------- |
||||
|
||||
@REM ---------------------------------------------------------------------------- |
||||
@REM Maven Start Up Batch script |
||||
@REM |
||||
@REM Required ENV vars: |
||||
@REM JAVA_HOME - location of a JDK home dir |
||||
@REM |
||||
@REM Optional ENV vars |
||||
@REM M2_HOME - location of maven2's installed home dir |
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands |
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending |
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven |
||||
@REM e.g. to debug Maven itself, use |
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 |
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files |
||||
@REM ---------------------------------------------------------------------------- |
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' |
||||
@echo off |
||||
@REM set title of command window |
||||
title %0 |
||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' |
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% |
||||
|
||||
@REM set %HOME% to equivalent of $HOME |
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") |
||||
|
||||
@REM Execute a user defined script before this one |
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre |
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending |
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" |
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" |
||||
:skipRcPre |
||||
|
||||
@setlocal |
||||
|
||||
set ERROR_CODE=0 |
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal |
||||
@setlocal |
||||
|
||||
@REM ==== START VALIDATION ==== |
||||
if not "%JAVA_HOME%" == "" goto OkJHome |
||||
|
||||
echo. |
||||
echo Error: JAVA_HOME not found in your environment. >&2 |
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2 |
||||
echo location of your Java installation. >&2 |
||||
echo. |
||||
goto error |
||||
|
||||
:OkJHome |
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init |
||||
|
||||
echo. |
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2 |
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2 |
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2 |
||||
echo location of your Java installation. >&2 |
||||
echo. |
||||
goto error |
||||
|
||||
@REM ==== END VALIDATION ==== |
||||
|
||||
:init |
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". |
||||
@REM Fallback to current working directory if not found. |
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% |
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir |
||||
|
||||
set EXEC_DIR=%CD% |
||||
set WDIR=%EXEC_DIR% |
||||
:findBaseDir |
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound |
||||
cd .. |
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound |
||||
set WDIR=%CD% |
||||
goto findBaseDir |
||||
|
||||
:baseDirFound |
||||
set MAVEN_PROJECTBASEDIR=%WDIR% |
||||
cd "%EXEC_DIR%" |
||||
goto endDetectBaseDir |
||||
|
||||
:baseDirNotFound |
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR% |
||||
cd "%EXEC_DIR%" |
||||
|
||||
:endDetectBaseDir |
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig |
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion |
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a |
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% |
||||
|
||||
:endReadAdditionalConfig |
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" |
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" |
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain |
||||
|
||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" |
||||
|
||||
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( |
||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B |
||||
) |
||||
|
||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central |
||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data. |
||||
if exist %WRAPPER_JAR% ( |
||||
if "%MVNW_VERBOSE%" == "true" ( |
||||
echo Found %WRAPPER_JAR% |
||||
) |
||||
) else ( |
||||
if not "%MVNW_REPOURL%" == "" ( |
||||
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" |
||||
) |
||||
if "%MVNW_VERBOSE%" == "true" ( |
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ... |
||||
echo Downloading from: %DOWNLOAD_URL% |
||||
) |
||||
|
||||
powershell -Command "&{"^ |
||||
"$webclient = new-object System.Net.WebClient;"^ |
||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ |
||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ |
||||
"}"^ |
||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ |
||||
"}" |
||||
if "%MVNW_VERBOSE%" == "true" ( |
||||
echo Finished downloading %WRAPPER_JAR% |
||||
) |
||||
) |
||||
@REM End of extension |
||||
|
||||
@REM Provide a "standardized" way to retrieve the CLI args that will |
||||
@REM work with both Windows and non-Windows executions. |
||||
set MAVEN_CMD_LINE_ARGS=%* |
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* |
||||
if ERRORLEVEL 1 goto error |
||||
goto end |
||||
|
||||
:error |
||||
set ERROR_CODE=1 |
||||
|
||||
:end |
||||
@endlocal & set ERROR_CODE=%ERROR_CODE% |
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost |
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending |
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" |
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" |
||||
:skipRcPost |
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' |
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause |
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% |
||||
|
||||
exit /B %ERROR_CODE% |
@ -0,0 +1,112 @@ |
||||
<?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.3.3.RELEASE</version> |
||||
<relativePath/> <!-- lookup parent from repository --> |
||||
</parent> |
||||
<groupId>com.msdw</groupId> |
||||
<artifactId>tms</artifactId> |
||||
<version>0.0.1-SNAPSHOT</version> |
||||
<name>tms</name> |
||||
<description>测评管理系统</description> |
||||
|
||||
<properties> |
||||
<java.version>1.8</java.version> |
||||
</properties> |
||||
|
||||
<dependencies> |
||||
<dependency> |
||||
<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> |
||||
<groupId>org.apache.poi</groupId> |
||||
<artifactId>poi-ooxml-schemas</artifactId> |
||||
<version>4.0.1</version> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-web</artifactId> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>com.baomidou</groupId> |
||||
<artifactId>mybatis-plus-boot-starter</artifactId> |
||||
<version>3.3.1</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.projectlombok</groupId> |
||||
<artifactId>lombok</artifactId> |
||||
<version>1.18.12</version> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>org.apache.httpcomponents</groupId> |
||||
<artifactId>httpcore</artifactId> |
||||
<version>4.4.13</version> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>commons-lang</groupId> |
||||
<artifactId>commons-lang</artifactId> |
||||
<version>2.6</version> |
||||
</dependency> |
||||
|
||||
<!--导入mysql的驱动--> |
||||
<dependency> |
||||
<groupId>mysql</groupId> |
||||
<artifactId>mysql-connector-java</artifactId> |
||||
<version>8.0.20</version> |
||||
</dependency> |
||||
|
||||
<!--swagger start--> |
||||
<dependency> |
||||
<groupId>io.springfox</groupId> |
||||
<artifactId>springfox-swagger-ui</artifactId> |
||||
<version>2.7.0</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>io.springfox</groupId> |
||||
<artifactId>springfox-swagger2</artifactId> |
||||
<version>2.7.0</version> |
||||
</dependency> |
||||
<!--swagger end--> |
||||
<dependency> |
||||
<groupId>com.aliyun.oss</groupId> |
||||
<artifactId>aliyun-sdk-oss</artifactId> |
||||
<version>2.8.2</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-test</artifactId> |
||||
<scope>test</scope> |
||||
<exclusions> |
||||
<exclusion> |
||||
<groupId>org.junit.vintage</groupId> |
||||
<artifactId>junit-vintage-engine</artifactId> |
||||
</exclusion> |
||||
</exclusions> |
||||
</dependency> |
||||
</dependencies> |
||||
|
||||
<build> |
||||
<plugins> |
||||
<plugin> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-maven-plugin</artifactId> |
||||
</plugin> |
||||
</plugins> |
||||
</build> |
||||
|
||||
</project> |
@ -0,0 +1,13 @@ |
||||
package com.msdw.tms; |
||||
|
||||
import org.springframework.boot.SpringApplication; |
||||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
|
||||
@SpringBootApplication |
||||
public class TmsApplication { |
||||
|
||||
public static void main(String[] args) { |
||||
SpringApplication.run(TmsApplication.class, args); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,33 @@ |
||||
package com.msdw.tms.api; |
||||
|
||||
import com.msdw.tms.common.utils.R; |
||||
import com.msdw.tms.entity.EvaluationRulesEntity; |
||||
import io.swagger.annotations.Api; |
||||
import io.swagger.annotations.ApiOperation; |
||||
import org.springframework.web.bind.annotation.*; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.Map; |
||||
|
||||
|
||||
/** |
||||
* 测评规则信息记录,只记录一条信息 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-19 09:28:06 |
||||
*/ |
||||
@Api(value = "测评规则管理", tags = "测评规则的查询和修改") |
||||
public interface EvaluationRulesControllerApi { |
||||
|
||||
/** |
||||
* 测评规则信息的展示 |
||||
*/ |
||||
@ApiOperation(value = "测评规则信息的展示", notes = "测评规则信息的展示") |
||||
R info(); |
||||
/** |
||||
* 修改测评规则信息 |
||||
*/ |
||||
@ApiOperation(value = "修改测评规则信息", notes = "修改测评规则信息") |
||||
R update(@RequestBody EvaluationRulesEntity evaluationRules); |
||||
} |
@ -0,0 +1,94 @@ |
||||
package com.msdw.tms.api; |
||||
|
||||
import com.msdw.tms.common.utils.R; |
||||
import com.msdw.tms.entity.request.QuestionsAddRequest; |
||||
import com.msdw.tms.entity.request.QuestionsQueryRequest; |
||||
import com.msdw.tms.entity.request.QuestionsUpdateRequest; |
||||
import io.swagger.annotations.Api; |
||||
import io.swagger.annotations.ApiOperation; |
||||
import org.springframework.web.bind.annotation.PathVariable; |
||||
import org.springframework.web.bind.annotation.RequestBody; |
||||
import org.springframework.web.bind.annotation.RequestParam; |
||||
import org.springframework.web.multipart.MultipartFile; |
||||
|
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.IOException; |
||||
|
||||
|
||||
/** |
||||
* 记录试题信息 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-19 09:28:06 |
||||
*/ |
||||
@Api(value = "试题信息管理", tags = "提供试题信息的增删改查及导入等功能") |
||||
public interface QuestionsControllerApi { |
||||
|
||||
/** |
||||
* 列表 |
||||
*/ |
||||
@ApiOperation(value = "分页加条件查询试题信息", notes = "分页加条件查询试题信息") |
||||
R list(@RequestParam Integer page, |
||||
@RequestParam Integer size, |
||||
QuestionsQueryRequest request); |
||||
|
||||
/** |
||||
* 信息 |
||||
*/ |
||||
@ApiOperation(value = "根据试题id查询试题详情信息", notes = "根据试题id查询试题详情信息") |
||||
R info(@PathVariable("id") Integer id); |
||||
|
||||
/** |
||||
* 保存 |
||||
*/ |
||||
@ApiOperation(value = "新增一道试题", notes = "传入新增试题所需相关参数") |
||||
R save(@RequestBody QuestionsAddRequest questions); |
||||
|
||||
/** |
||||
* 根据试题id修改试题信息 |
||||
*/ |
||||
@ApiOperation(value = "根据试题id修改试题信息", notes = "根据试题id修改试题信息") |
||||
R update(@RequestBody QuestionsUpdateRequest questions); |
||||
|
||||
/** |
||||
* 是否禁用试题 |
||||
*/ |
||||
@ApiOperation(value = "是否禁用试题", notes = "是否禁用试题") |
||||
R isnable(Integer id); |
||||
|
||||
/** |
||||
* 删除 |
||||
*/ |
||||
@ApiOperation(value = "批量删除试题信息", notes = "批量删除试题信息") |
||||
R delete(@RequestBody Integer[] ids); |
||||
|
||||
/** |
||||
* 通过excel批量导入 |
||||
*/ |
||||
@ApiOperation(value = "通过excel批量导入", notes = "通过excel批量导入") |
||||
R importQuestion(@RequestParam(name = "file") MultipartFile file) throws IOException; |
||||
|
||||
/** |
||||
* excel模板文件上传 |
||||
* |
||||
* @param file |
||||
* @return |
||||
*/ |
||||
@ApiOperation(value = "excel模板文件上传", notes = "excel模板文件上传") |
||||
R uploadFiles(MultipartFile file) throws IOException; |
||||
|
||||
/** |
||||
* excel模板文件下载 |
||||
* |
||||
* @return |
||||
*/ |
||||
@ApiOperation(value = "excel模板文件下载", notes = "excel模板文件下载") |
||||
R downloadFiles(HttpServletResponse response) throws IOException; |
||||
|
||||
/** |
||||
* 抽题测评 |
||||
*/ |
||||
@ApiOperation(value = "抽题测评", notes = "抽题测评") |
||||
R evaluation (); |
||||
} |
@ -0,0 +1,21 @@ |
||||
package com.msdw.tms.common.exception; |
||||
|
||||
import com.msdw.tms.entity.response.ResultCode; |
||||
|
||||
/** |
||||
* @author 世杰 |
||||
* @date 2020/3/24 22:47 |
||||
*/ |
||||
public class CustomException extends RuntimeException { |
||||
private ResultCode resultCode; |
||||
|
||||
public CustomException(ResultCode resultCode) { |
||||
//异常信息为错误代码+异常信息
|
||||
super("错误代码:" + resultCode.code() + "错误信息:" + resultCode.message()); |
||||
this.resultCode = resultCode; |
||||
} |
||||
|
||||
public ResultCode getResultCode() { |
||||
return this.resultCode; |
||||
} |
||||
} |
@ -0,0 +1,14 @@ |
||||
package com.msdw.tms.common.exception; |
||||
|
||||
import com.msdw.tms.entity.response.ResultCode; |
||||
|
||||
/** |
||||
* @author 世杰 |
||||
* @date 2020/3/24 23:04 |
||||
*/ |
||||
public class ExceptionCast { |
||||
//使用此静态方法抛出自定义异常
|
||||
public static void cast(ResultCode resultCode) { |
||||
throw new CustomException(resultCode); |
||||
} |
||||
} |
@ -0,0 +1,62 @@ |
||||
package com.msdw.tms.common.exception; |
||||
|
||||
import com.google.common.collect.ImmutableMap; |
||||
import com.msdw.tms.entity.response.CommonCode; |
||||
import com.msdw.tms.entity.response.ResponseResult; |
||||
import com.msdw.tms.entity.response.ResultCode; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.http.converter.HttpMessageNotReadableException; |
||||
import org.springframework.web.bind.annotation.ControllerAdvice; |
||||
import org.springframework.web.bind.annotation.ExceptionHandler; |
||||
import org.springframework.web.bind.annotation.ResponseBody; |
||||
|
||||
|
||||
/** |
||||
* @author 世杰 |
||||
* @date 2020/3/24 23:06 |
||||
*/ |
||||
//使用 @ControllerAdvice和@ExceptionHandler注解来捕获指定类型的异常
|
||||
@ControllerAdvice//控制器增强
|
||||
public class ExceptionCatch { |
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionCatch.class); |
||||
|
||||
//定义Map,配置异常类型所对应的错误代码,使用 ImmutableMap 一旦写入数据,就无法更改,只读并且线程安全
|
||||
private static ImmutableMap<Class<? extends Throwable>, ResultCode> EXCEPTIONS; |
||||
//定义map的builder对象,去构建ImmutableMap
|
||||
protected static ImmutableMap.Builder<Class<? extends Throwable>, ResultCode> builder = ImmutableMap.builder(); |
||||
|
||||
@ExceptionHandler(Exception.class) |
||||
@ResponseBody |
||||
public ResponseResult exception(Exception exception) { |
||||
exception.printStackTrace(); |
||||
//记录日志
|
||||
LOGGER.error("catch exception:{}", exception.getMessage()); |
||||
if (EXCEPTIONS == null) { |
||||
EXCEPTIONS = builder.build();//EXCEPTION构建成功
|
||||
} |
||||
//从EXCEPTIONS中找到异常类型所对应的错误代码,如果找到了,将错误代码相应给用户,如果找不到则给用户相应99999
|
||||
ResultCode resultCode = EXCEPTIONS.get(exception.getClass()); |
||||
if (resultCode != null) { |
||||
return new ResponseResult(resultCode); |
||||
} |
||||
//返回99999异常
|
||||
return new ResponseResult(CommonCode.SERVER_ERROR); |
||||
} |
||||
|
||||
static { |
||||
//定义异常类型所对应的错误代码
|
||||
builder.put(HttpMessageNotReadableException.class, CommonCode.INVALID_PARAM); |
||||
} |
||||
|
||||
@ExceptionHandler(CustomException.class)//捕获CustomException类型异常
|
||||
@ResponseBody |
||||
public ResponseResult customException(CustomException customException) { |
||||
customException.printStackTrace(); |
||||
//记录日志
|
||||
LOGGER.error("catch exception:{}", customException.getMessage()); |
||||
|
||||
ResultCode resultCode = customException.getResultCode(); |
||||
return new ResponseResult(resultCode); |
||||
} |
||||
} |
@ -0,0 +1,61 @@ |
||||
/** |
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved. |
||||
* |
||||
* https://www.renren.io
|
||||
* |
||||
* 版权所有,侵权必究! |
||||
*/ |
||||
|
||||
package com.msdw.tms.common.exception; |
||||
|
||||
/** |
||||
* 自定义异常 |
||||
* |
||||
* @author Mark sunlightcs@gmail.com |
||||
*/ |
||||
public class RRException extends RuntimeException { |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
private String msg; |
||||
private int code = 500; |
||||
|
||||
public RRException(String msg) { |
||||
super(msg); |
||||
this.msg = msg; |
||||
} |
||||
|
||||
public RRException(String msg, Throwable e) { |
||||
super(msg, e); |
||||
this.msg = msg; |
||||
} |
||||
|
||||
public RRException(String msg, int code) { |
||||
super(msg); |
||||
this.msg = msg; |
||||
this.code = code; |
||||
} |
||||
|
||||
public RRException(String msg, int code, Throwable e) { |
||||
super(msg, e); |
||||
this.msg = msg; |
||||
this.code = code; |
||||
} |
||||
|
||||
public String getMsg() { |
||||
return msg; |
||||
} |
||||
|
||||
public void setMsg(String msg) { |
||||
this.msg = msg; |
||||
} |
||||
|
||||
public int getCode() { |
||||
return code; |
||||
} |
||||
|
||||
public void setCode(int code) { |
||||
this.code = code; |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,315 @@ |
||||
package com.msdw.tms.common.utils; |
||||
|
||||
import com.aliyun.oss.ClientException; |
||||
import com.aliyun.oss.OSSClient; |
||||
import com.aliyun.oss.OSSException; |
||||
import com.aliyun.oss.model.*; |
||||
import com.msdw.tms.config.AliyunOssConfig; |
||||
import org.springframework.web.multipart.MultipartFile; |
||||
|
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.ByteArrayInputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.OutputStream; |
||||
import java.net.URLEncoder; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.Date; |
||||
|
||||
|
||||
public class AliyunOssUtil { |
||||
|
||||
private static String sdf = new SimpleDateFormat("yyyyMMdd").format(new Date()); |
||||
|
||||
/** |
||||
* 创建存储空间 |
||||
* |
||||
* @param client |
||||
* @param config |
||||
*/ |
||||
public static void createBucket(OSSClient client, AliyunOssConfig config) { |
||||
// 判断存储空间是否存在,不存在,则创建
|
||||
if (!client.doesBucketExist(config.getBucketName())) { |
||||
CreateBucketRequest bucketRequest = new CreateBucketRequest(null); |
||||
// 设置仓库名称
|
||||
bucketRequest.setBucketName(config.getBucketName()); |
||||
// 设置仓库权限
|
||||
bucketRequest.setCannedACL(CannedAccessControlList.PublicRead); |
||||
// 创建仓库
|
||||
client.createBucket(bucketRequest); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 上传文件 |
||||
* |
||||
* @param file 需要上传的文件 |
||||
* @param client |
||||
* @param config |
||||
* @return |
||||
* @throws OSSException |
||||
* @throws ClientException |
||||
* @throws IOException |
||||
*/ |
||||
public static FilesResult uploadFiles(MultipartFile file, OSSClient client, AliyunOssConfig config) throws OSSException, ClientException, IOException { |
||||
FilesResult result = new FilesResult(); |
||||
// 创建存储空间
|
||||
createBucket(client, config); |
||||
// 获取文件名
|
||||
String fileUrl = file.getOriginalFilename(); |
||||
// 获取文件尾缀
|
||||
String ext = fileUrl.substring(fileUrl.lastIndexOf(".")); |
||||
// 获取文件类型
|
||||
String fileType = getFileType(ext); |
||||
//创建文件
|
||||
String folderName = ext.substring(ext.indexOf(".") + 1); |
||||
String folder = createFolder(client, config.getBucketName(), folderName); |
||||
// 组合储存路径
|
||||
String fileName = folder + "/" + sdf + "/" + System.currentTimeMillis() + ext; |
||||
long fileSize = file.getSize(); |
||||
|
||||
ObjectMetadata metadata = new ObjectMetadata(); |
||||
// 指定该Object被下载时的网页的缓存行为
|
||||
metadata.setCacheControl("no-cache"); |
||||
// 指定该Object下设置Header
|
||||
metadata.setHeader("Pragma", "no-cache"); |
||||
// 指定该Object被下载时的内容编码格式
|
||||
metadata.setContentEncoding("utf-8"); |
||||
// 文件的MIME,定义文件的类型及网页编码,决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成,
|
||||
// 如果没有扩展名则填默认值application/octet-stream
|
||||
metadata.setContentType(fileType); |
||||
// 指定该Object被下载时的名称(指示MINME用户代理如何显示附加的文件,打开或下载,及文件名称)
|
||||
metadata.setContentDisposition("filename/filesize=" + file.getName() + "/" + fileSize + "Byte."); |
||||
// 上传文件 (上传文件流的形式)
|
||||
client.putObject(config.getBucketName(), fileName, new ByteArrayInputStream(file.getBytes()), metadata); |
||||
result.setFileName(fileName); |
||||
result.setFileUrl(config.getSufferUrl() + fileName); |
||||
|
||||
if (null != client) |
||||
client.shutdown(); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* 用户头像上传 |
||||
* |
||||
* @param file 需要上传的文件 |
||||
* @param client |
||||
* @param config |
||||
* @return |
||||
* @throws OSSException |
||||
* @throws ClientException |
||||
* @throws IOException |
||||
*/ |
||||
public static FilesResult uploadUserAvatars(MultipartFile file, OSSClient client, AliyunOssConfig config) throws OSSException, ClientException, IOException { |
||||
FilesResult result = new FilesResult(); |
||||
String userAvatars = config.getUserAvatars(); |
||||
// 创建存储空间
|
||||
createBucket(client, config); |
||||
// 获取文件名
|
||||
String fileUrl = file.getOriginalFilename(); |
||||
// 获取文件尾缀
|
||||
String ext = fileUrl.substring(fileUrl.lastIndexOf(".")); |
||||
// 获取文件类型
|
||||
String fileType = getFileType(ext); |
||||
// 组合储存路径
|
||||
String fileName = userAvatars + "/" + sdf + "/" + System.currentTimeMillis() + ext; |
||||
long fileSize = file.getSize(); |
||||
|
||||
ObjectMetadata metadata = new ObjectMetadata(); |
||||
// 指定该Object被下载时的网页的缓存行为
|
||||
metadata.setCacheControl("no-cache"); |
||||
// 指定该Object下设置Header
|
||||
metadata.setHeader("Pragma", "no-cache"); |
||||
// 指定该Object被下载时的内容编码格式
|
||||
metadata.setContentEncoding("utf-8"); |
||||
// 文件的MIME,定义文件的类型及网页编码,决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成,
|
||||
// 如果没有扩展名则填默认值application/octet-stream
|
||||
metadata.setContentType(fileType); |
||||
// 指定该Object被下载时的名称(指示MINME用户代理如何显示附加的文件,打开或下载,及文件名称)
|
||||
metadata.setContentDisposition("filename/filesize=" + file.getName() + "/" + fileSize + "Byte."); |
||||
// 上传文件 (上传文件流的形式)
|
||||
client.putObject(config.getBucketName(), fileName, new ByteArrayInputStream(file.getBytes()), metadata); |
||||
result.setFileName(fileName); |
||||
result.setFileUrl(config.getSufferUrl() + fileName); |
||||
|
||||
if (null != client) |
||||
client.shutdown(); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* 简单上传 |
||||
* |
||||
* @param client |
||||
* @param config |
||||
* @param objectName 表示上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。 |
||||
* @param stream |
||||
* @return |
||||
*/ |
||||
public static FilesResult uploadFiles(OSSClient client, AliyunOssConfig config, String objectName, ByteArrayInputStream stream) { |
||||
FilesResult result = new FilesResult(); |
||||
try { |
||||
PutObjectRequest putObjectRequest = new PutObjectRequest(config.getBucketName(), objectName, stream); |
||||
client.putObject(putObjectRequest); |
||||
result.setFileName(objectName); |
||||
result.setFileUrl(config.getSufferUrl() + objectName); |
||||
|
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
throw e; |
||||
} finally { |
||||
if (null != client) |
||||
client.shutdown(); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* 文件下载 |
||||
* |
||||
* @param response |
||||
* @param client |
||||
* @param config |
||||
* @param objectName |
||||
*/ |
||||
public static void downloadFiles(HttpServletResponse response, OSSClient client, AliyunOssConfig config, |
||||
String objectName) throws IOException { |
||||
|
||||
OSSObject ossObject = client.getObject(config.getBucketName(), objectName); |
||||
InputStream input = null; |
||||
OutputStream outputStream = null; |
||||
try { |
||||
// 获取文件名
|
||||
String fileName = objectName.substring(objectName.lastIndexOf("/") + 1); |
||||
//获取输入流
|
||||
input = ossObject.getObjectContent(); |
||||
// 获取OutputStream输出流
|
||||
outputStream = response.getOutputStream(); |
||||
byte[] buffer = new byte[input.available()]; |
||||
|
||||
response.setHeader("content-Type", "application/vnd.ms-excel"); |
||||
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); |
||||
response.flushBuffer(); |
||||
|
||||
for (int length = 0; (length = input.read(buffer)) > 0; ) { |
||||
outputStream.write(buffer, 0, length); |
||||
} |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
throw e; |
||||
} finally { |
||||
if (null != outputStream) { |
||||
try { |
||||
outputStream.close(); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
if (null != input) { |
||||
try { |
||||
input.close(); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
if (null != client) |
||||
client.shutdown(); |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* 删除存储空间buckName |
||||
* |
||||
* @param ossClient oss对象 |
||||
* @param bucketName 存储空间 |
||||
*/ |
||||
public static void deleteBucket(OSSClient ossClient, String bucketName) { |
||||
ossClient.deleteBucket(bucketName); |
||||
} |
||||
|
||||
/** |
||||
* 创建模拟文件夹 |
||||
* |
||||
* @param ossClient oss连接 |
||||
* @param bucketName 存储空间 |
||||
* @param folder 模拟文件夹名如"qj_nanjing/" |
||||
* @return |
||||
*/ |
||||
public static String createFolder(OSSClient ossClient, String bucketName, String folder) { |
||||
// 文件夹名
|
||||
final String keySuffixWithSlash = folder; |
||||
// 判断文件夹是否存在,不存在则创建
|
||||
if (!ossClient.doesObjectExist(bucketName, keySuffixWithSlash)) { |
||||
// 创建文件夹
|
||||
ossClient.putObject(bucketName, keySuffixWithSlash, new ByteArrayInputStream(new byte[0])); |
||||
// 得到文件夹名
|
||||
OSSObject object = ossClient.getObject(bucketName, keySuffixWithSlash); |
||||
String fileDir = object.getKey(); |
||||
return fileDir; |
||||
} |
||||
return keySuffixWithSlash; |
||||
} |
||||
|
||||
/** |
||||
* 根据key删除OSS服务器上的文件 |
||||
* |
||||
* @param ossClient oss连接 |
||||
* @param bucketName 存储空间 |
||||
* @param fileName 模拟文件夹名 如"qj_nanjing/" |
||||
*/ |
||||
public static void deleteFile(OSSClient ossClient, String bucketName, String fileName) { |
||||
ossClient.deleteObject(bucketName, fileName); |
||||
} |
||||
|
||||
/** |
||||
* 获取文件类型 |
||||
* |
||||
* @param fileExtension 文件后缀 |
||||
* @return |
||||
*/ |
||||
public static String getFileType(String fileExtension) { |
||||
if (".bmp".equalsIgnoreCase(fileExtension)) { |
||||
return "image/bmp"; |
||||
} |
||||
if (".gif".equalsIgnoreCase(fileExtension)) { |
||||
return "image/gif"; |
||||
} |
||||
if (".jpeg".equalsIgnoreCase(fileExtension) || ".jpg".equalsIgnoreCase(fileExtension) |
||||
|| ".png".equalsIgnoreCase(fileExtension)) { |
||||
return "image/jpg"; |
||||
} |
||||
if (".html".equalsIgnoreCase(fileExtension)) { |
||||
return "text/html"; |
||||
} |
||||
if (".txt".equalsIgnoreCase(fileExtension)) { |
||||
return "text/plain"; |
||||
} |
||||
if (".vsd".equalsIgnoreCase(fileExtension)) { |
||||
return "application/vnd.visio"; |
||||
} |
||||
if (".ppt".equalsIgnoreCase(fileExtension) || ".pptx".equalsIgnoreCase(fileExtension)) { |
||||
return "application/vnd.ms-powerpoint"; |
||||
} |
||||
if (".doc".equalsIgnoreCase(fileExtension) || ".docx".equalsIgnoreCase(fileExtension)) { |
||||
return "application/msword"; |
||||
} |
||||
if (".xml".equalsIgnoreCase(fileExtension)) { |
||||
return "text/xml"; |
||||
} |
||||
if (".mp4".equalsIgnoreCase(fileExtension) || ".avi".equalsIgnoreCase(fileExtension)) { |
||||
return "video/mp4"; |
||||
} |
||||
if (".mpg".equalsIgnoreCase(fileExtension) || ".mpeg".equalsIgnoreCase(fileExtension)) { |
||||
return "video/mpeg"; |
||||
} |
||||
if ("pdf".equalsIgnoreCase(fileExtension)) { |
||||
return "application/pdf"; |
||||
} |
||||
return "application/octet-stream"; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,340 @@ |
||||
/** |
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved. |
||||
* <p> |
||||
* https://www.renren.io
|
||||
* <p> |
||||
* 版权所有,侵权必究! |
||||
*/ |
||||
|
||||
package com.msdw.tms.common.utils; |
||||
|
||||
/** |
||||
* 常量 |
||||
* |
||||
* @author Mark sunlightcs@gmail.com |
||||
*/ |
||||
public class Constant { |
||||
/** |
||||
* 超级管理员ID |
||||
*/ |
||||
public static final int SUPER_ADMIN = 1; |
||||
/** |
||||
* 当前页码 |
||||
*/ |
||||
public static final String PAGE = "page"; |
||||
/** |
||||
* 每页显示记录数 |
||||
*/ |
||||
public static final String LIMIT = "limit"; |
||||
/** |
||||
* 排序字段 |
||||
*/ |
||||
public static final String ORDER_FIELD = "sidx"; |
||||
/** |
||||
* 排序方式 |
||||
*/ |
||||
public static final String ORDER = "order"; |
||||
/** |
||||
* 升序 |
||||
*/ |
||||
public static final String ASC = "asc"; |
||||
/** |
||||
* 通过excel批量导入试题数据时起始行 |
||||
*/ |
||||
public static final int STARTING_ROW = 2; |
||||
/** |
||||
* 通过excel批量导入试题数据时起始列 |
||||
*/ |
||||
public static final int STARTING_CELL = 0; |
||||
/** |
||||
* 试题选项A |
||||
*/ |
||||
public static final String A = "A"; |
||||
/** |
||||
* 试题选项B |
||||
*/ |
||||
public static final String B = "B"; |
||||
/** |
||||
* 试题选项C |
||||
*/ |
||||
public static final String C = "C"; |
||||
/** |
||||
* 试题选项D |
||||
*/ |
||||
public static final String D = "D"; |
||||
/** |
||||
* 试题选项E |
||||
*/ |
||||
public static final String E = "E"; |
||||
/** |
||||
* 试题选项F |
||||
*/ |
||||
public static final String F = "F"; |
||||
/** |
||||
* excel模板信息表id |
||||
*/ |
||||
public static final int XLSX_TEMPLATE_ID = 1; |
||||
/** |
||||
* 测评规则表id |
||||
*/ |
||||
public static final int EVALUATION_RULES_ID = 1; |
||||
/** |
||||
* 菜单类型 |
||||
* |
||||
* @author chenshun |
||||
* @email sunlightcs@gmail.com |
||||
* @date 2016年11月15日 下午1:24:29 |
||||
*/ |
||||
public enum MenuType { |
||||
/** |
||||
* 目录 |
||||
*/ |
||||
CATALOG(0), |
||||
/** |
||||
* 菜单 |
||||
*/ |
||||
MENU(1), |
||||
/** |
||||
* 按钮 |
||||
*/ |
||||
BUTTON(2); |
||||
|
||||
private int value; |
||||
|
||||
MenuType(int value) { |
||||
this.value = value; |
||||
} |
||||
|
||||
public int getValue() { |
||||
return value; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 定时任务状态 |
||||
* |
||||
* @author chenshun |
||||
* @email sunlightcs@gmail.com |
||||
* @date 2016年12月3日 上午12:07:22 |
||||
*/ |
||||
public enum ScheduleStatus { |
||||
/** |
||||
* 正常 |
||||
*/ |
||||
NORMAL(0), |
||||
/** |
||||
* 暂停 |
||||
*/ |
||||
PAUSE(1); |
||||
|
||||
private int value; |
||||
|
||||
ScheduleStatus(int value) { |
||||
this.value = value; |
||||
} |
||||
|
||||
public int getValue() { |
||||
return value; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 云服务商 |
||||
*/ |
||||
public enum CloudService { |
||||
/** |
||||
* 七牛云 |
||||
*/ |
||||
QINIU(1), |
||||
/** |
||||
* 阿里云 |
||||
*/ |
||||
ALIYUN(2), |
||||
/** |
||||
* 腾讯云 |
||||
*/ |
||||
QCLOUD(3); |
||||
|
||||
private int value; |
||||
|
||||
CloudService(int value) { |
||||
this.value = value; |
||||
} |
||||
|
||||
public int getValue() { |
||||
return value; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 是否启用 |
||||
*/ |
||||
public enum IsEnable { |
||||
/** |
||||
* 启用 |
||||
*/ |
||||
ENABLE(1, "启用"), |
||||
/** |
||||
* 不启用 |
||||
*/ |
||||
NOT_ENABLE(0, "不启用"); |
||||
|
||||
private Integer type; //类型
|
||||
private String desc; //描述
|
||||
|
||||
IsEnable(Integer type, String desc) { |
||||
this.type = type; |
||||
this.desc = desc; |
||||
} |
||||
|
||||
public Integer getType() { |
||||
return type; |
||||
} |
||||
|
||||
public void setType(Integer type) { |
||||
this.type = type; |
||||
} |
||||
|
||||
public String getDesc() { |
||||
return desc; |
||||
} |
||||
|
||||
public void setDesc(String desc) { |
||||
this.desc = desc; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 是否删除 |
||||
*/ |
||||
public enum IsDel { |
||||
/** |
||||
* 删除 |
||||
*/ |
||||
DEL(0, "删除"), |
||||
/** |
||||
* 不删除 |
||||
*/ |
||||
NOT_DEL(1, "不删除"); |
||||
|
||||
private Integer type; //类型
|
||||
private String desc; //描述
|
||||
|
||||
IsDel(Integer type, String desc) { |
||||
this.type = type; |
||||
this.desc = desc; |
||||
} |
||||
|
||||
public Integer getType() { |
||||
return type; |
||||
} |
||||
|
||||
public void setType(Integer type) { |
||||
this.type = type; |
||||
} |
||||
|
||||
public String getDesc() { |
||||
return desc; |
||||
} |
||||
|
||||
public void setDesc(String desc) { |
||||
this.desc = desc; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 评测规则类型 |
||||
*/ |
||||
public enum RulesType { |
||||
/** |
||||
* 随机 |
||||
*/ |
||||
RANDOM(0, "随机"), |
||||
/** |
||||
* 自定义 |
||||
*/ |
||||
CUSTOMIZE(1, "自定义"); |
||||
|
||||
private Integer type; //类型
|
||||
private String desc; //描述
|
||||
|
||||
RulesType(Integer type, String desc) { |
||||
this.type = type; |
||||
this.desc = desc; |
||||
} |
||||
|
||||
public Integer getType() { |
||||
return type; |
||||
} |
||||
|
||||
public void setType(Integer type) { |
||||
this.type = type; |
||||
} |
||||
|
||||
public String getDesc() { |
||||
return desc; |
||||
} |
||||
|
||||
public void setDesc(String desc) { |
||||
this.desc = desc; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 试题类型 |
||||
*/ |
||||
public enum QuestionType { |
||||
/** |
||||
* 单选题 |
||||
*/ |
||||
SINGLE_CHOICE(1, "单选题"), |
||||
/** |
||||
* 多选题 |
||||
*/ |
||||
MULTIPLE_CHOICE(2, "多选题"), |
||||
/** |
||||
* 判断题 |
||||
*/ |
||||
TRUE_OR_FALSE(3, "判断题"); |
||||
|
||||
private Integer type; //类型
|
||||
private String desc; //描述
|
||||
|
||||
QuestionType(Integer type, String desc) { |
||||
this.type = type; |
||||
this.desc = desc; |
||||
} |
||||
|
||||
public Integer getType() { |
||||
return type; |
||||
} |
||||
|
||||
public void setType(Integer type) { |
||||
this.type = type; |
||||
} |
||||
|
||||
public String getDesc() { |
||||
return desc; |
||||
} |
||||
|
||||
public void setDesc(String desc) { |
||||
this.desc = desc; |
||||
} |
||||
} |
||||
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// String answer = "A";
|
||||
//// System.out.println(answer.length());//3
|
||||
//// System.out.println(answer.charAt(2));//E
|
||||
//
|
||||
// String str = "";
|
||||
// for (int i = 0; i < answer.length(); i++) {
|
||||
// char c = answer.charAt(i);
|
||||
// str += c + ",";
|
||||
// }
|
||||
// str = str.substring(0, str.length() - 1);
|
||||
// System.out.println(str);
|
||||
// }
|
||||
} |
@ -0,0 +1,41 @@ |
||||
package com.msdw.tms.common.utils; |
||||
|
||||
public class FilesResult { |
||||
|
||||
// 文件名
|
||||
private String fileName; |
||||
// 文件在储存空间的路径
|
||||
private String fileUrl; |
||||
// 上传状态
|
||||
private String status; |
||||
|
||||
public String getFileName() { |
||||
return fileName; |
||||
} |
||||
|
||||
public void setFileName(String fileName) { |
||||
this.fileName = fileName; |
||||
} |
||||
|
||||
public String getFileUrl() { |
||||
return fileUrl; |
||||
} |
||||
|
||||
public void setFileUrl(String fileUrl) { |
||||
this.fileUrl = fileUrl; |
||||
} |
||||
|
||||
public String getStatus() { |
||||
return status; |
||||
} |
||||
|
||||
public void setStatus(String status) { |
||||
this.status = status; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "UploadFilesResult [fileName=" + fileName + ", fileUrl=" + fileUrl + ", status=" + status + "]"; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,110 @@ |
||||
/** |
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved. |
||||
* |
||||
* https://www.renren.io
|
||||
* |
||||
* 版权所有,侵权必究! |
||||
*/ |
||||
|
||||
package com.msdw.tms.common.utils; |
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 分页工具类 |
||||
* |
||||
* @author Mark sunlightcs@gmail.com |
||||
*/ |
||||
public class PageUtils implements Serializable { |
||||
private static final long serialVersionUID = 1L; |
||||
/** |
||||
* 总记录数 |
||||
*/ |
||||
private int totalCount; |
||||
/** |
||||
* 每页记录数 |
||||
*/ |
||||
private int pageSize; |
||||
/** |
||||
* 总页数 |
||||
*/ |
||||
private int totalPage; |
||||
/** |
||||
* 当前页数 |
||||
*/ |
||||
private int currPage; |
||||
/** |
||||
* 列表数据 |
||||
*/ |
||||
private List<?> list; |
||||
|
||||
/** |
||||
* 分页 |
||||
* @param list 列表数据 |
||||
* @param totalCount 总记录数 |
||||
* @param pageSize 每页记录数 |
||||
* @param currPage 当前页数 |
||||
*/ |
||||
public PageUtils(List<?> list, int totalCount, int pageSize, int currPage) { |
||||
this.list = list; |
||||
this.totalCount = totalCount; |
||||
this.pageSize = pageSize; |
||||
this.currPage = currPage; |
||||
this.totalPage = (int)Math.ceil((double)totalCount/pageSize); |
||||
} |
||||
|
||||
/** |
||||
* 分页 |
||||
*/ |
||||
public PageUtils(IPage<?> page) { |
||||
this.list = page.getRecords(); |
||||
this.totalCount = (int)page.getTotal(); |
||||
this.pageSize = (int)page.getSize(); |
||||
this.currPage = (int)page.getCurrent(); |
||||
this.totalPage = (int)page.getPages(); |
||||
} |
||||
|
||||
public int getTotalCount() { |
||||
return totalCount; |
||||
} |
||||
|
||||
public void setTotalCount(int totalCount) { |
||||
this.totalCount = totalCount; |
||||
} |
||||
|
||||
public int getPageSize() { |
||||
return pageSize; |
||||
} |
||||
|
||||
public void setPageSize(int pageSize) { |
||||
this.pageSize = pageSize; |
||||
} |
||||
|
||||
public int getTotalPage() { |
||||
return totalPage; |
||||
} |
||||
|
||||
public void setTotalPage(int totalPage) { |
||||
this.totalPage = totalPage; |
||||
} |
||||
|
||||
public int getCurrPage() { |
||||
return currPage; |
||||
} |
||||
|
||||
public void setCurrPage(int currPage) { |
||||
this.currPage = currPage; |
||||
} |
||||
|
||||
public List<?> getList() { |
||||
return list; |
||||
} |
||||
|
||||
public void setList(List<?> list) { |
||||
this.list = list; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,94 @@ |
||||
/** |
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved. |
||||
* <p> |
||||
* https://www.renren.io
|
||||
* <p> |
||||
* 版权所有,侵权必究! |
||||
*/ |
||||
|
||||
package com.msdw.tms.common.utils; |
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem; |
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
import com.msdw.tms.common.xss.SQLFilter; |
||||
import org.apache.commons.lang.StringUtils; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 查询参数 |
||||
* |
||||
* @author Mark sunlightcs@gmail.com |
||||
*/ |
||||
public class Query<T> { |
||||
|
||||
public IPage<T> getPage(Map<String, Object> params) { |
||||
return this.getPage(params, null, false); |
||||
} |
||||
|
||||
public IPage<T> getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc) { |
||||
//分页参数
|
||||
long curPage = 1; |
||||
long limit = 10; |
||||
|
||||
if (params.get(Constant.PAGE) != null) { |
||||
curPage = Long.parseLong((String) params.get(Constant.PAGE)); |
||||
} |
||||
if (params.get(Constant.LIMIT) != null) { |
||||
limit = Long.parseLong((String) params.get(Constant.LIMIT)); |
||||
} |
||||
|
||||
//分页对象
|
||||
Page<T> page = new Page<>(curPage, limit); |
||||
|
||||
//分页参数
|
||||
params.put(Constant.PAGE, page); |
||||
|
||||
//排序字段
|
||||
//防止SQL注入(因为sidx、order是通过拼接SQL实现排序的,会有SQL注入风险)
|
||||
String orderField = SQLFilter.sqlInject((String) params.get(Constant.ORDER_FIELD)); |
||||
String order = (String) params.get(Constant.ORDER); |
||||
|
||||
//前端字段排序
|
||||
if (StringUtils.isNotEmpty(orderField) && StringUtils.isNotEmpty(order)) { |
||||
if (Constant.ASC.equalsIgnoreCase(order)) { |
||||
return page.addOrder(OrderItem.asc(orderField)); |
||||
} else { |
||||
return page.addOrder(OrderItem.desc(orderField)); |
||||
} |
||||
} |
||||
|
||||
//没有排序字段,则不排序
|
||||
if (StringUtils.isBlank(defaultOrderField)) { |
||||
return page; |
||||
} |
||||
|
||||
//默认排序
|
||||
if (isAsc) { |
||||
page.addOrder(OrderItem.asc(defaultOrderField)); |
||||
} else { |
||||
page.addOrder(OrderItem.desc(defaultOrderField)); |
||||
} |
||||
|
||||
return page; |
||||
} |
||||
|
||||
public IPage<T> getPage(Integer pageNo, Integer size) { |
||||
//分页参数
|
||||
long curPage = 1; |
||||
long limit = 10; |
||||
|
||||
if (pageNo != null) { |
||||
curPage = Long.parseLong(pageNo.toString()); |
||||
} |
||||
if (size != null) { |
||||
limit = Long.parseLong(size.toString()); |
||||
} |
||||
|
||||
//分页对象
|
||||
Page<T> page = new Page<>(curPage, limit); |
||||
|
||||
return page; |
||||
} |
||||
} |
@ -0,0 +1,64 @@ |
||||
/** |
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved. |
||||
* |
||||
* https://www.renren.io
|
||||
* |
||||
* 版权所有,侵权必究! |
||||
*/ |
||||
|
||||
package com.msdw.tms.common.utils; |
||||
|
||||
import org.apache.http.HttpStatus; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 返回数据 |
||||
* |
||||
* @author Mark sunlightcs@gmail.com |
||||
*/ |
||||
public class R extends HashMap<String, Object> { |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
public R() { |
||||
put("code", 0); |
||||
put("msg", "success"); |
||||
} |
||||
|
||||
public static R error() { |
||||
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员"); |
||||
} |
||||
|
||||
public static R error(String msg) { |
||||
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg); |
||||
} |
||||
|
||||
public static R error(int code, String msg) { |
||||
R r = new R(); |
||||
r.put("code", code); |
||||
r.put("msg", msg); |
||||
return r; |
||||
} |
||||
|
||||
public static R ok(String msg) { |
||||
R r = new R(); |
||||
r.put("msg", msg); |
||||
return r; |
||||
} |
||||
|
||||
public static R ok(Map<String, Object> map) { |
||||
R r = new R(); |
||||
r.putAll(map); |
||||
return r; |
||||
} |
||||
|
||||
public static R ok() { |
||||
return new R(); |
||||
} |
||||
|
||||
public R put(String key, Object value) { |
||||
super.put(key, value); |
||||
return this; |
||||
} |
||||
} |
@ -0,0 +1,25 @@ |
||||
package com.msdw.tms.common.utils.poi; |
||||
|
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Target(ElementType.FIELD) |
||||
public @interface ExcelAttribute { |
||||
/** |
||||
* 对应的列名称 |
||||
*/ |
||||
String name() default ""; |
||||
|
||||
/** |
||||
* excel列的索引 |
||||
*/ |
||||
int sort(); |
||||
|
||||
/** |
||||
* 字段类型对应的格式 |
||||
*/ |
||||
String format() default ""; |
||||
} |
@ -0,0 +1,87 @@ |
||||
package com.msdw.tms.common.utils.poi; |
||||
|
||||
import lombok.Data; |
||||
import org.apache.poi.ss.usermodel.Cell; |
||||
import org.apache.poi.ss.usermodel.CellStyle; |
||||
import org.apache.poi.ss.usermodel.Row; |
||||
import org.apache.poi.ss.usermodel.Sheet; |
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
||||
|
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.InputStream; |
||||
import java.lang.reflect.Field; |
||||
import java.net.URLEncoder; |
||||
import java.util.List; |
||||
import java.util.concurrent.atomic.AtomicInteger; |
||||
|
||||
/** |
||||
* 导出Excel工具类 |
||||
* 基于模板打印的方式导出: |
||||
*/ |
||||
@Data |
||||
public class ExcelExportUtil<T> { |
||||
|
||||
private int rowIndex; //写入数据的起始行
|
||||
private int styleIndex; //需要提取的样式所在的行号
|
||||
private Class clazz; //对象的字节码
|
||||
private Field fields[]; //对象中的所有属性
|
||||
|
||||
public ExcelExportUtil(Class clazz, int rowIndex, int styleIndex) { |
||||
this.clazz = clazz; |
||||
this.rowIndex = rowIndex; |
||||
this.styleIndex = styleIndex; |
||||
fields = clazz.getDeclaredFields(); |
||||
} |
||||
|
||||
/** |
||||
* 基于注解导出 |
||||
* 参数: |
||||
* response: |
||||
* InputStream:模板的输入流 |
||||
* objs:数据 |
||||
* fileName:生成的文件名 |
||||
*/ |
||||
public void export(HttpServletResponse response, InputStream is, List<T> objs, String fileName) throws Exception { |
||||
|
||||
//1.根据模板创建工作簿
|
||||
XSSFWorkbook workbook = new XSSFWorkbook(is); |
||||
//2.读取工作表
|
||||
Sheet sheet = workbook.getSheetAt(0); |
||||
//3.提取公共的样式
|
||||
CellStyle[] styles = getTemplateStyles(sheet.getRow(styleIndex)); |
||||
//4.根据数据创建每一行和每一个单元格的数据2
|
||||
AtomicInteger datasAi = new AtomicInteger(rowIndex); //数字
|
||||
for (T t : objs) { |
||||
//datasAi.getAndIncrement() :获取数字,并++ i++
|
||||
Row row = sheet.createRow(datasAi.getAndIncrement()); |
||||
for (int i = 0; i < styles.length; i++) { |
||||
Cell cell = row.createCell(i); |
||||
cell.setCellStyle(styles[i]); |
||||
for (Field field : fields) { |
||||
if (field.isAnnotationPresent(ExcelAttribute.class)) { |
||||
field.setAccessible(true); |
||||
ExcelAttribute ea = field.getAnnotation(ExcelAttribute.class); |
||||
if (i == ea.sort()) { |
||||
if (field.get(t) != null) { |
||||
cell.setCellValue(field.get(t).toString()); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
fileName = URLEncoder.encode(fileName, "UTF-8"); |
||||
response.setContentType("application/octet-stream"); |
||||
response.setHeader("content-disposition", "attachment;filename=" + new String(fileName.getBytes("ISO8859-1"))); |
||||
response.setHeader("filename", fileName); |
||||
workbook.write(response.getOutputStream()); |
||||
} |
||||
|
||||
public CellStyle[] getTemplateStyles(Row row) { |
||||
CellStyle[] styles = new CellStyle[row.getLastCellNum()]; |
||||
for (int i = 0; i < row.getLastCellNum(); i++) { |
||||
styles[i] = row.getCell(i).getCellStyle(); |
||||
} |
||||
return styles; |
||||
} |
||||
} |
@ -0,0 +1,120 @@ |
||||
package com.msdw.tms.common.utils.poi; |
||||
|
||||
import org.apache.poi.ss.usermodel.Cell; |
||||
import org.apache.poi.ss.usermodel.DateUtil; |
||||
import org.apache.poi.ss.usermodel.Row; |
||||
import org.apache.poi.ss.usermodel.Sheet; |
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
||||
|
||||
import java.io.InputStream; |
||||
import java.lang.reflect.Field; |
||||
import java.math.BigDecimal; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.ArrayList; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
|
||||
|
||||
public class ExcelImportUtil<T> { |
||||
|
||||
private Class clazz; |
||||
private Field fields[]; |
||||
|
||||
public ExcelImportUtil(Class clazz) { |
||||
this.clazz = clazz; |
||||
fields = clazz.getDeclaredFields(); |
||||
} |
||||
|
||||
/** |
||||
* 基于注解读取excel |
||||
*/ |
||||
public List<T> readExcel(InputStream is, int rowIndex, int cellIndex) { |
||||
List<T> list = new ArrayList<T>(); |
||||
T entity = null; |
||||
try { |
||||
XSSFWorkbook workbook = new XSSFWorkbook(is); |
||||
Sheet sheet = workbook.getSheetAt(0); |
||||
// 不准确
|
||||
// int rowLength = sheet.getLastRowNum();
|
||||
// System.out.println(sheet.getLastRowNum());
|
||||
for (int rowNum = rowIndex; rowNum <= sheet.getLastRowNum(); rowNum++) { |
||||
Row row = sheet.getRow(rowNum); |
||||
entity = (T) clazz.newInstance(); |
||||
// System.out.println(row.getLastCellNum());
|
||||
for (int j = cellIndex; j < row.getLastCellNum(); j++) { |
||||
Cell cell = row.getCell(j); |
||||
for (Field field : fields) { |
||||
if (field.isAnnotationPresent(ExcelAttribute.class)) { |
||||
field.setAccessible(true); |
||||
ExcelAttribute ea = field.getAnnotation(ExcelAttribute.class); |
||||
if (j == ea.sort()) { |
||||
field.set(entity, covertAttrType(field, cell)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
list.add(entity); |
||||
} |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
return list; |
||||
} |
||||
|
||||
/** |
||||
* 类型转换 将cell 单元格格式转为 字段类型 |
||||
*/ |
||||
private Object covertAttrType(Field field, Cell cell) throws Exception { |
||||
String fieldType = field.getType().getSimpleName(); |
||||
if ("String".equals(fieldType)) { |
||||
return getValue(cell); |
||||
} else if ("Date".equals(fieldType)) { |
||||
return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(getValue(cell)); |
||||
} else if ("int".equals(fieldType) || "Integer".equals(fieldType)) { |
||||
return Integer.parseInt(getValue(cell)); |
||||
} else if ("double".equals(fieldType) || "Double".equals(fieldType)) { |
||||
return Double.parseDouble(getValue(cell)); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 格式转为String |
||||
* |
||||
* @param cell |
||||
* @return |
||||
*/ |
||||
public String getValue(Cell cell) { |
||||
if (cell == null) { |
||||
return ""; |
||||
} |
||||
switch (cell.getCellType()) { |
||||
case STRING: |
||||
return cell.getRichStringCellValue().getString().trim(); |
||||
case NUMERIC: |
||||
if (DateUtil.isCellDateFormatted(cell)) { |
||||
Date dt = DateUtil.getJavaDate(cell.getNumericCellValue()); |
||||
return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(dt); |
||||
} else { |
||||
// 防止数值变成科学计数法
|
||||
String strCell = ""; |
||||
Double num = cell.getNumericCellValue(); |
||||
BigDecimal bd = new BigDecimal(num.toString()); |
||||
if (bd != null) { |
||||
strCell = bd.toPlainString(); |
||||
} |
||||
// 去除 浮点型 自动加的 .0
|
||||
if (strCell.endsWith(".0")) { |
||||
strCell = strCell.substring(0, strCell.indexOf(".")); |
||||
} |
||||
return strCell; |
||||
} |
||||
case BOOLEAN: |
||||
return String.valueOf(cell.getBooleanCellValue()); |
||||
default: |
||||
return ""; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,530 @@ |
||||
package com.msdw.tms.common.xss; |
||||
|
||||
import java.util.*; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.concurrent.ConcurrentMap; |
||||
import java.util.logging.Logger; |
||||
import java.util.regex.Matcher; |
||||
import java.util.regex.Pattern; |
||||
|
||||
/** |
||||
* |
||||
* HTML filtering utility for protecting against XSS (Cross Site Scripting). |
||||
* |
||||
* This code is licensed LGPLv3 |
||||
* |
||||
* This code is a Java port of the original work in PHP by Cal Hendersen. |
||||
* http://code.iamcal.com/php/lib_filter/
|
||||
* |
||||
* The trickiest part of the translation was handling the differences in regex handling |
||||
* between PHP and Java. These resources were helpful in the process: |
||||
* |
||||
* http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html
|
||||
* http://us2.php.net/manual/en/reference.pcre.pattern.modifiers.php
|
||||
* http://www.regular-expressions.info/modifiers.html
|
||||
* |
||||
* A note on naming conventions: instance variables are prefixed with a "v"; global |
||||
* constants are in all caps. |
||||
* |
||||
* Sample use: |
||||
* String input = ... |
||||
* String clean = new HTMLFilter().filter( input ); |
||||
* |
||||
* The class is not thread safe. Create a new instance if in doubt. |
||||
* |
||||
* If you find bugs or have suggestions on improvement (especially regarding |
||||
* performance), please contact us. The latest version of this |
||||
* source, and our contact details, can be found at http://xss-html-filter.sf.net
|
||||
* |
||||
* @author Joseph O'Connell |
||||
* @author Cal Hendersen |
||||
* @author Michael Semb Wever |
||||
*/ |
||||
public final class HTMLFilter { |
||||
|
||||
/** regex flag union representing /si modifiers in php **/ |
||||
private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; |
||||
private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL); |
||||
private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI); |
||||
private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL); |
||||
private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI); |
||||
private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI); |
||||
private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI); |
||||
private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI); |
||||
private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI); |
||||
private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?"); |
||||
private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?"); |
||||
private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?"); |
||||
private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))"); |
||||
private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL); |
||||
private static final Pattern P_END_ARROW = Pattern.compile("^>"); |
||||
private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)"); |
||||
private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)"); |
||||
private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)"); |
||||
private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)"); |
||||
private static final Pattern P_AMP = Pattern.compile("&"); |
||||
private static final Pattern P_QUOTE = Pattern.compile("<"); |
||||
private static final Pattern P_LEFT_ARROW = Pattern.compile("<"); |
||||
private static final Pattern P_RIGHT_ARROW = Pattern.compile(">"); |
||||
private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); |
||||
|
||||
// @xxx could grow large... maybe use sesat's ReferenceMap
|
||||
private static final ConcurrentMap<String,Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<String, Pattern>(); |
||||
private static final ConcurrentMap<String,Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<String, Pattern>(); |
||||
|
||||
/** set of allowed html elements, along with allowed attributes for each element **/ |
||||
private final Map<String, List<String>> vAllowed; |
||||
/** counts of open tags for each (allowable) html element **/ |
||||
private final Map<String, Integer> vTagCounts = new HashMap<String, Integer>(); |
||||
|
||||
/** html elements which must always be self-closing (e.g. "<img />") **/ |
||||
private final String[] vSelfClosingTags; |
||||
/** html elements which must always have separate opening and closing tags (e.g. "<b></b>") **/ |
||||
private final String[] vNeedClosingTags; |
||||
/** set of disallowed html elements **/ |
||||
private final String[] vDisallowed; |
||||
/** attributes which should be checked for valid protocols **/ |
||||
private final String[] vProtocolAtts; |
||||
/** allowed protocols **/ |
||||
private final String[] vAllowedProtocols; |
||||
/** tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />") **/ |
||||
private final String[] vRemoveBlanks; |
||||
/** entities allowed within html markup **/ |
||||
private final String[] vAllowedEntities; |
||||
/** flag determining whether comments are allowed in input String. */ |
||||
private final boolean stripComment; |
||||
private final boolean encodeQuotes; |
||||
private boolean vDebug = false; |
||||
/** |
||||
* flag determining whether to try to make tags when presented with "unbalanced" |
||||
* angle brackets (e.g. "<b text </b>" becomes "<b> text </b>"). If set to false, |
||||
* unbalanced angle brackets will be html escaped. |
||||
*/ |
||||
private final boolean alwaysMakeTags; |
||||
|
||||
/** Default constructor. |
||||
* |
||||
*/ |
||||
public HTMLFilter() { |
||||
vAllowed = new HashMap<>(); |
||||
|
||||
final ArrayList<String> a_atts = new ArrayList<String>(); |
||||
a_atts.add("href"); |
||||
a_atts.add("target"); |
||||
vAllowed.put("a", a_atts); |
||||
|
||||
final ArrayList<String> img_atts = new ArrayList<String>(); |
||||
img_atts.add("src"); |
||||
img_atts.add("width"); |
||||
img_atts.add("height"); |
||||
img_atts.add("alt"); |
||||
vAllowed.put("img", img_atts); |
||||
|
||||
final ArrayList<String> no_atts = new ArrayList<String>(); |
||||
vAllowed.put("b", no_atts); |
||||
vAllowed.put("strong", no_atts); |
||||
vAllowed.put("i", no_atts); |
||||
vAllowed.put("em", no_atts); |
||||
|
||||
vSelfClosingTags = new String[]{"img"}; |
||||
vNeedClosingTags = new String[]{"a", "b", "strong", "i", "em"}; |
||||
vDisallowed = new String[]{}; |
||||
vAllowedProtocols = new String[]{"http", "mailto", "https"}; // no ftp.
|
||||
vProtocolAtts = new String[]{"src", "href"}; |
||||
vRemoveBlanks = new String[]{"a", "b", "strong", "i", "em"}; |
||||
vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"}; |
||||
stripComment = true; |
||||
encodeQuotes = true; |
||||
alwaysMakeTags = true; |
||||
} |
||||
|
||||
/** Set debug flag to true. Otherwise use default settings. See the default constructor. |
||||
* |
||||
* @param debug turn debug on with a true argument |
||||
*/ |
||||
public HTMLFilter(final boolean debug) { |
||||
this(); |
||||
vDebug = debug; |
||||
|
||||
} |
||||
|
||||
/** Map-parameter configurable constructor. |
||||
* |
||||
* @param conf map containing configuration. keys match field names. |
||||
*/ |
||||
public HTMLFilter(final Map<String,Object> conf) { |
||||
|
||||
assert conf.containsKey("vAllowed") : "configuration requires vAllowed"; |
||||
assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags"; |
||||
assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags"; |
||||
assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed"; |
||||
assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols"; |
||||
assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts"; |
||||
assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks"; |
||||
assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities"; |
||||
|
||||
vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed")); |
||||
vSelfClosingTags = (String[]) conf.get("vSelfClosingTags"); |
||||
vNeedClosingTags = (String[]) conf.get("vNeedClosingTags"); |
||||
vDisallowed = (String[]) conf.get("vDisallowed"); |
||||
vAllowedProtocols = (String[]) conf.get("vAllowedProtocols"); |
||||
vProtocolAtts = (String[]) conf.get("vProtocolAtts"); |
||||
vRemoveBlanks = (String[]) conf.get("vRemoveBlanks"); |
||||
vAllowedEntities = (String[]) conf.get("vAllowedEntities"); |
||||
stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true; |
||||
encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true; |
||||
alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true; |
||||
} |
||||
|
||||
private void reset() { |
||||
vTagCounts.clear(); |
||||
} |
||||
|
||||
private void debug(final String msg) { |
||||
if (vDebug) { |
||||
Logger.getAnonymousLogger().info(msg); |
||||
} |
||||
} |
||||
|
||||
//---------------------------------------------------------------
|
||||
// my versions of some PHP library functions
|
||||
public static String chr(final int decimal) { |
||||
return String.valueOf((char) decimal); |
||||
} |
||||
|
||||
public static String htmlSpecialChars(final String s) { |
||||
String result = s; |
||||
result = regexReplace(P_AMP, "&", result); |
||||
result = regexReplace(P_QUOTE, """, result); |
||||
result = regexReplace(P_LEFT_ARROW, "<", result); |
||||
result = regexReplace(P_RIGHT_ARROW, ">", result); |
||||
return result; |
||||
} |
||||
|
||||
//---------------------------------------------------------------
|
||||
/** |
||||
* given a user submitted input String, filter out any invalid or restricted |
||||
* html. |
||||
* |
||||
* @param input text (i.e. submitted by a user) than may contain html |
||||
* @return "clean" version of input, with only valid, whitelisted html elements allowed |
||||
*/ |
||||
public String filter(final String input) { |
||||
reset(); |
||||
String s = input; |
||||
|
||||
debug("************************************************"); |
||||
debug(" INPUT: " + input); |
||||
|
||||
s = escapeComments(s); |
||||
debug(" escapeComments: " + s); |
||||
|
||||
s = balanceHTML(s); |
||||
debug(" balanceHTML: " + s); |
||||
|
||||
s = checkTags(s); |
||||
debug(" checkTags: " + s); |
||||
|
||||
s = processRemoveBlanks(s); |
||||
debug("processRemoveBlanks: " + s); |
||||
|
||||
s = validateEntities(s); |
||||
debug(" validateEntites: " + s); |
||||
|
||||
debug("************************************************\n\n"); |
||||
return s; |
||||
} |
||||
|
||||
public boolean isAlwaysMakeTags(){ |
||||
return alwaysMakeTags; |
||||
} |
||||
|
||||
public boolean isStripComments(){ |
||||
return stripComment; |
||||
} |
||||
|
||||
private String escapeComments(final String s) { |
||||
final Matcher m = P_COMMENTS.matcher(s); |
||||
final StringBuffer buf = new StringBuffer(); |
||||
if (m.find()) { |
||||
final String match = m.group(1); //(.*?)
|
||||
m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->")); |
||||
} |
||||
m.appendTail(buf); |
||||
|
||||
return buf.toString(); |
||||
} |
||||
|
||||
private String balanceHTML(String s) { |
||||
if (alwaysMakeTags) { |
||||
//
|
||||
// try and form html
|
||||
//
|
||||
s = regexReplace(P_END_ARROW, "", s); |
||||
s = regexReplace(P_BODY_TO_END, "<$1>", s); |
||||
s = regexReplace(P_XML_CONTENT, "$1<$2", s); |
||||
|
||||
} else { |
||||
//
|
||||
// escape stray brackets
|
||||
//
|
||||
s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); |
||||
s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); |
||||
|
||||
//
|
||||
// the last regexp causes '<>' entities to appear
|
||||
// (we need to do a lookahead assertion so that the last bracket can
|
||||
// be used in the next pass of the regexp)
|
||||
//
|
||||
s = regexReplace(P_BOTH_ARROWS, "", s); |
||||
} |
||||
|
||||
return s; |
||||
} |
||||
|
||||
private String checkTags(String s) { |
||||
Matcher m = P_TAGS.matcher(s); |
||||
|
||||
final StringBuffer buf = new StringBuffer(); |
||||
while (m.find()) { |
||||
String replaceStr = m.group(1); |
||||
replaceStr = processTag(replaceStr); |
||||
m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); |
||||
} |
||||
m.appendTail(buf); |
||||
|
||||
s = buf.toString(); |
||||
|
||||
// these get tallied in processTag
|
||||
// (remember to reset before subsequent calls to filter method)
|
||||
for (String key : vTagCounts.keySet()) { |
||||
for (int ii = 0; ii < vTagCounts.get(key); ii++) { |
||||
s += "</" + key + ">"; |
||||
} |
||||
} |
||||
|
||||
return s; |
||||
} |
||||
|
||||
private String processRemoveBlanks(final String s) { |
||||
String result = s; |
||||
for (String tag : vRemoveBlanks) { |
||||
if(!P_REMOVE_PAIR_BLANKS.containsKey(tag)){ |
||||
P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">")); |
||||
} |
||||
result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); |
||||
if(!P_REMOVE_SELF_BLANKS.containsKey(tag)){ |
||||
P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); |
||||
} |
||||
result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) { |
||||
Matcher m = regex_pattern.matcher(s); |
||||
return m.replaceAll(replacement); |
||||
} |
||||
|
||||
private String processTag(final String s) { |
||||
// ending tags
|
||||
Matcher m = P_END_TAG.matcher(s); |
||||
if (m.find()) { |
||||
final String name = m.group(1).toLowerCase(); |
||||
if (allowed(name)) { |
||||
if (!inArray(name, vSelfClosingTags)) { |
||||
if (vTagCounts.containsKey(name)) { |
||||
vTagCounts.put(name, vTagCounts.get(name) - 1); |
||||
return "</" + name + ">"; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// starting tags
|
||||
m = P_START_TAG.matcher(s); |
||||
if (m.find()) { |
||||
final String name = m.group(1).toLowerCase(); |
||||
final String body = m.group(2); |
||||
String ending = m.group(3); |
||||
|
||||
//debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
|
||||
if (allowed(name)) { |
||||
String params = ""; |
||||
|
||||
final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body); |
||||
final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body); |
||||
final List<String> paramNames = new ArrayList<String>(); |
||||
final List<String> paramValues = new ArrayList<String>(); |
||||
while (m2.find()) { |
||||
paramNames.add(m2.group(1)); //([a-z0-9]+)
|
||||
paramValues.add(m2.group(3)); //(.*?)
|
||||
} |
||||
while (m3.find()) { |
||||
paramNames.add(m3.group(1)); //([a-z0-9]+)
|
||||
paramValues.add(m3.group(3)); //([^\"\\s']+)
|
||||
} |
||||
|
||||
String paramName, paramValue; |
||||
for (int ii = 0; ii < paramNames.size(); ii++) { |
||||
paramName = paramNames.get(ii).toLowerCase(); |
||||
paramValue = paramValues.get(ii); |
||||
|
||||
// debug( "paramName='" + paramName + "'" );
|
||||
// debug( "paramValue='" + paramValue + "'" );
|
||||
// debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
|
||||
|
||||
if (allowedAttribute(name, paramName)) { |
||||
if (inArray(paramName, vProtocolAtts)) { |
||||
paramValue = processParamProtocol(paramValue); |
||||
} |
||||
params += " " + paramName + "=\"" + paramValue + "\""; |
||||
} |
||||
} |
||||
|
||||
if (inArray(name, vSelfClosingTags)) { |
||||
ending = " /"; |
||||
} |
||||
|
||||
if (inArray(name, vNeedClosingTags)) { |
||||
ending = ""; |
||||
} |
||||
|
||||
if (ending == null || ending.length() < 1) { |
||||
if (vTagCounts.containsKey(name)) { |
||||
vTagCounts.put(name, vTagCounts.get(name) + 1); |
||||
} else { |
||||
vTagCounts.put(name, 1); |
||||
} |
||||
} else { |
||||
ending = " /"; |
||||
} |
||||
return "<" + name + params + ending + ">"; |
||||
} else { |
||||
return ""; |
||||
} |
||||
} |
||||
|
||||
// comments
|
||||
m = P_COMMENT.matcher(s); |
||||
if (!stripComment && m.find()) { |
||||
return "<" + m.group() + ">"; |
||||
} |
||||
|
||||
return ""; |
||||
} |
||||
|
||||
private String processParamProtocol(String s) { |
||||
s = decodeEntities(s); |
||||
final Matcher m = P_PROTOCOL.matcher(s); |
||||
if (m.find()) { |
||||
final String protocol = m.group(1); |
||||
if (!inArray(protocol, vAllowedProtocols)) { |
||||
// bad protocol, turn into local anchor link instead
|
||||
s = "#" + s.substring(protocol.length() + 1, s.length()); |
||||
if (s.startsWith("#//")) { |
||||
s = "#" + s.substring(3, s.length()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return s; |
||||
} |
||||
|
||||
private String decodeEntities(String s) { |
||||
StringBuffer buf = new StringBuffer(); |
||||
|
||||
Matcher m = P_ENTITY.matcher(s); |
||||
while (m.find()) { |
||||
final String match = m.group(1); |
||||
final int decimal = Integer.decode(match).intValue(); |
||||
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); |
||||
} |
||||
m.appendTail(buf); |
||||
s = buf.toString(); |
||||
|
||||
buf = new StringBuffer(); |
||||
m = P_ENTITY_UNICODE.matcher(s); |
||||
while (m.find()) { |
||||
final String match = m.group(1); |
||||
final int decimal = Integer.valueOf(match, 16).intValue(); |
||||
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); |
||||
} |
||||
m.appendTail(buf); |
||||
s = buf.toString(); |
||||
|
||||
buf = new StringBuffer(); |
||||
m = P_ENCODE.matcher(s); |
||||
while (m.find()) { |
||||
final String match = m.group(1); |
||||
final int decimal = Integer.valueOf(match, 16).intValue(); |
||||
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); |
||||
} |
||||
m.appendTail(buf); |
||||
s = buf.toString(); |
||||
|
||||
s = validateEntities(s); |
||||
return s; |
||||
} |
||||
|
||||
private String validateEntities(final String s) { |
||||
StringBuffer buf = new StringBuffer(); |
||||
|
||||
// validate entities throughout the string
|
||||
Matcher m = P_VALID_ENTITIES.matcher(s); |
||||
while (m.find()) { |
||||
final String one = m.group(1); //([^&;]*)
|
||||
final String two = m.group(2); //(?=(;|&|$))
|
||||
m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); |
||||
} |
||||
m.appendTail(buf); |
||||
|
||||
return encodeQuotes(buf.toString()); |
||||
} |
||||
|
||||
private String encodeQuotes(final String s){ |
||||
if(encodeQuotes){ |
||||
StringBuffer buf = new StringBuffer(); |
||||
Matcher m = P_VALID_QUOTES.matcher(s); |
||||
while (m.find()) { |
||||
final String one = m.group(1); //(>|^)
|
||||
final String two = m.group(2); //([^<]+?)
|
||||
final String three = m.group(3); //(<|$)
|
||||
m.appendReplacement(buf, Matcher.quoteReplacement(one + regexReplace(P_QUOTE, """, two) + three)); |
||||
} |
||||
m.appendTail(buf); |
||||
return buf.toString(); |
||||
}else{ |
||||
return s; |
||||
} |
||||
} |
||||
|
||||
private String checkEntity(final String preamble, final String term) { |
||||
|
||||
return ";".equals(term) && isValidEntity(preamble) |
||||
? '&' + preamble |
||||
: "&" + preamble; |
||||
} |
||||
|
||||
private boolean isValidEntity(final String entity) { |
||||
return inArray(entity, vAllowedEntities); |
||||
} |
||||
|
||||
private static boolean inArray(final String s, final String[] array) { |
||||
for (String item : array) { |
||||
if (item != null && item.equals(s)) { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
private boolean allowed(final String name) { |
||||
return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); |
||||
} |
||||
|
||||
private boolean allowedAttribute(final String name, final String paramName) { |
||||
return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); |
||||
} |
||||
} |
@ -0,0 +1,50 @@ |
||||
/** |
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved. |
||||
* |
||||
* https://www.renren.io
|
||||
* |
||||
* 版权所有,侵权必究! |
||||
*/ |
||||
|
||||
package com.msdw.tms.common.xss; |
||||
|
||||
import com.msdw.tms.common.exception.RRException; |
||||
import org.apache.commons.lang.StringUtils; |
||||
|
||||
/** |
||||
* SQL过滤 |
||||
* |
||||
* @author Mark sunlightcs@gmail.com |
||||
*/ |
||||
public class SQLFilter { |
||||
|
||||
/** |
||||
* SQL注入过滤 |
||||
* @param str 待验证的字符串 |
||||
*/ |
||||
public static String sqlInject(String str){ |
||||
if(StringUtils.isBlank(str)){ |
||||
return null; |
||||
} |
||||
//去掉'|"|;|\字符
|
||||
str = StringUtils.replace(str, "'", ""); |
||||
str = StringUtils.replace(str, "\"", ""); |
||||
str = StringUtils.replace(str, ";", ""); |
||||
str = StringUtils.replace(str, "\\", ""); |
||||
|
||||
//转换成小写
|
||||
str = str.toLowerCase(); |
||||
|
||||
//非法字符
|
||||
String[] keywords = {"master", "truncate", "insert", "select", "delete", "update", "declare", "alter", "drop"}; |
||||
|
||||
//判断是否包含非法字符
|
||||
for(String keyword : keywords){ |
||||
if(str.indexOf(keyword) != -1){ |
||||
throw new RRException("包含非法字符"); |
||||
} |
||||
} |
||||
|
||||
return str; |
||||
} |
||||
} |
@ -0,0 +1,59 @@ |
||||
package com.msdw.tms.config; |
||||
|
||||
import com.aliyun.oss.OSSClient; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.context.annotation.PropertySource; |
||||
import org.springframework.context.annotation.Scope; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
@Component |
||||
@PropertySource(value = "classpath:aliyun.properties") |
||||
@Configuration |
||||
public class AliyunOssConfig { |
||||
|
||||
@Value("${oss.endpoint}") |
||||
private String endpoint;// oss外网访问域名
|
||||
@Value("${oss.accessKeyId}") |
||||
private String accessKeyId;// oss中的密匙keyId
|
||||
@Value("${oss.secretAccessKey}") |
||||
private String secretAccessKey;// oss中的密钥
|
||||
@Value("${oss.bucketName}") |
||||
private String bucketName;// 仓库名称
|
||||
@Value("${oss.sufferUrl}") |
||||
private String sufferUrl; |
||||
@Value("${user.userAvatars}")//用户头像
|
||||
private String userAvatars; |
||||
|
||||
@Bean |
||||
@Scope("prototype") |
||||
public OSSClient ossClient() { |
||||
return new OSSClient(endpoint, accessKeyId, secretAccessKey); |
||||
} |
||||
|
||||
public String getEndpoint() { |
||||
return endpoint; |
||||
} |
||||
|
||||
public String getAccessKeyId() { |
||||
return accessKeyId; |
||||
} |
||||
|
||||
public String getSecretAccessKey() { |
||||
return secretAccessKey; |
||||
} |
||||
|
||||
public String getBucketName() { |
||||
return bucketName; |
||||
} |
||||
|
||||
public String getSufferUrl() { |
||||
return sufferUrl; |
||||
} |
||||
|
||||
public String getUserAvatars() { |
||||
return userAvatars; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,35 @@ |
||||
package com.msdw.tms.config; |
||||
|
||||
import io.swagger.annotations.ApiOperation; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import springfox.documentation.builders.ApiInfoBuilder; |
||||
import springfox.documentation.builders.PathSelectors; |
||||
import springfox.documentation.builders.RequestHandlerSelectors; |
||||
import springfox.documentation.service.ApiInfo; |
||||
import springfox.documentation.spi.DocumentationType; |
||||
import springfox.documentation.spring.web.plugins.Docket; |
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2; |
||||
|
||||
@Configuration |
||||
@EnableSwagger2 |
||||
//@Profile({"dev","test"})
|
||||
//@ConditionalOnProperty(name = "swagger.enable", havingValue = "true")
|
||||
public class SwaggerConfig { |
||||
|
||||
@Bean |
||||
public Docket productApi() { |
||||
return new Docket(DocumentationType.SWAGGER_2) |
||||
.apiInfo(apiInfo()) |
||||
.select()//添加ApiOperiation注解的被扫描
|
||||
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) |
||||
.paths(PathSelectors.any()) |
||||
.build(); |
||||
} |
||||
|
||||
private ApiInfo apiInfo() { |
||||
return new ApiInfoBuilder().title("网站管理").description("网站管理") |
||||
.version("1.0").build(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,49 @@ |
||||
package com.msdw.tms.controller; |
||||
|
||||
import com.msdw.tms.api.EvaluationRulesControllerApi; |
||||
import com.msdw.tms.common.utils.R; |
||||
import com.msdw.tms.entity.EvaluationRulesEntity; |
||||
import com.msdw.tms.entity.vo.EvaluationRulesVO; |
||||
import com.msdw.tms.service.EvaluationRulesService; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.web.bind.annotation.*; |
||||
|
||||
|
||||
/** |
||||
* 测评规则信息记录,只记录一条信息 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-19 09:28:06 |
||||
*/ |
||||
@RestController |
||||
@RequestMapping("tms/evaluationrules") |
||||
public class EvaluationRulesController implements EvaluationRulesControllerApi { |
||||
@Autowired |
||||
private EvaluationRulesService evaluationRulesService; |
||||
|
||||
/** |
||||
* 测评规则信息的展示 |
||||
*/ |
||||
@Override |
||||
@GetMapping("/info") |
||||
//@RequiresPermissions("qms:evaluationrules:info")
|
||||
public R info() { |
||||
EvaluationRulesVO evaluationRulesVO = evaluationRulesService.getEvaluationRules(); |
||||
|
||||
return R.ok().put("data", evaluationRulesVO); |
||||
} |
||||
|
||||
/** |
||||
* 修改 |
||||
*/ |
||||
@Override |
||||
@PutMapping("/update") |
||||
//@RequiresPermissions("qms:evaluationrules:update")
|
||||
public R update(@RequestBody EvaluationRulesEntity evaluationRules) { |
||||
boolean b = evaluationRulesService.updateEvaluationRulesById(evaluationRules); |
||||
|
||||
return b ? R.ok() : R.error(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,160 @@ |
||||
package com.msdw.tms.controller; |
||||
|
||||
import com.msdw.tms.api.QuestionsControllerApi; |
||||
import com.msdw.tms.common.utils.FilesResult; |
||||
import com.msdw.tms.common.utils.PageUtils; |
||||
import com.msdw.tms.common.utils.R; |
||||
import com.msdw.tms.entity.request.QuestionsAddRequest; |
||||
import com.msdw.tms.entity.request.QuestionsQueryRequest; |
||||
import com.msdw.tms.entity.request.QuestionsUpdateRequest; |
||||
import com.msdw.tms.entity.vo.EvaluationVO; |
||||
import com.msdw.tms.entity.vo.QuestionsDetailVO; |
||||
import com.msdw.tms.service.AliyunOssService; |
||||
import com.msdw.tms.service.QuestionsService; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.web.bind.annotation.*; |
||||
import org.springframework.web.multipart.MultipartFile; |
||||
|
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.IOException; |
||||
import java.util.Arrays; |
||||
|
||||
|
||||
/** |
||||
* 记录试题信息 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-19 09:28:06 |
||||
*/ |
||||
@RestController |
||||
@RequestMapping("tms/questions") |
||||
public class QuestionsController implements QuestionsControllerApi { |
||||
@Autowired |
||||
private QuestionsService questionsService; |
||||
|
||||
@Autowired |
||||
private AliyunOssService ossService; |
||||
|
||||
/** |
||||
* 列表 |
||||
*/ |
||||
@Override |
||||
@GetMapping("/list") |
||||
//@RequiresPermissions("qms:questions:list")
|
||||
public R list(@RequestParam Integer page, |
||||
@RequestParam Integer size, |
||||
QuestionsQueryRequest request) { |
||||
|
||||
PageUtils questionsQueryPage = questionsService.queryQuestionsPage(page, size, request); |
||||
|
||||
return R.ok().put("page", questionsQueryPage); |
||||
} |
||||
|
||||
/** |
||||
* 信息 |
||||
*/ |
||||
@Override |
||||
@GetMapping("/info/{id}") |
||||
//@RequiresPermissions("qms:questions:info")
|
||||
public R info(@PathVariable("id") Integer id) { |
||||
QuestionsDetailVO questions = questionsService.getQuestionDetailById(id); |
||||
|
||||
return R.ok().put("questions", questions); |
||||
} |
||||
|
||||
/** |
||||
* 保存 |
||||
*/ |
||||
@Override |
||||
@PostMapping("/save") |
||||
//@RequiresPermissions("qms:questions:save")
|
||||
public R save(@RequestBody QuestionsAddRequest questions) { |
||||
boolean save = questionsService.saveQuestion(questions); |
||||
|
||||
return save ? R.ok() : R.error(); |
||||
} |
||||
|
||||
/** |
||||
* 根据试题id修改试题信息 |
||||
*/ |
||||
@Override |
||||
@PutMapping("/update") |
||||
//@RequiresPermissions("qms:questions:update")
|
||||
public R update(@RequestBody QuestionsUpdateRequest questions) { |
||||
boolean update = questionsService.updateQuestionById(questions); |
||||
|
||||
return update ? R.ok() : R.error(); |
||||
} |
||||
|
||||
/** |
||||
* 是否禁用试题 |
||||
*/ |
||||
@Override |
||||
@PutMapping("/isnable") |
||||
//@RequiresPermissions("qms:questions:isnable")
|
||||
public R isnable(Integer id) { |
||||
boolean b = questionsService.isnable(id); |
||||
|
||||
return b ? R.ok() : R.error(); |
||||
} |
||||
|
||||
/** |
||||
* 删除 |
||||
*/ |
||||
@Override |
||||
@DeleteMapping("/delete") |
||||
//@RequiresPermissions("qms:questions:delete")
|
||||
public R delete(@RequestBody Integer[] ids) { |
||||
boolean delete = questionsService.deleteByIds(Arrays.asList(ids)); |
||||
|
||||
return delete ? R.ok() : R.error(); |
||||
} |
||||
|
||||
/** |
||||
* 通过excel批量导入 |
||||
*/ |
||||
@Override |
||||
@PostMapping("/import") |
||||
//@RequiresPermissions("qms:questions:import")
|
||||
public R importQuestion(@RequestParam(name = "file") MultipartFile file) throws IOException { |
||||
boolean b = questionsService.importQuestion(file); |
||||
|
||||
return b ? R.ok() : R.error(); |
||||
} |
||||
|
||||
/** |
||||
* excel模板文件上传 |
||||
* |
||||
* @param file |
||||
* @return |
||||
*/ |
||||
@Override |
||||
@PostMapping("/upload") |
||||
//@RequiresPermissions("qms:questions:upload")
|
||||
public R uploadFiles(MultipartFile file) throws IOException { |
||||
FilesResult filesResult = questionsService.uploadFiles(file); |
||||
return R.ok().put("data", filesResult); |
||||
} |
||||
|
||||
/** |
||||
* excel模板文件下载 |
||||
* |
||||
* @return |
||||
*/ |
||||
@Override |
||||
@GetMapping("/download") |
||||
//@RequiresPermissions("qms:questions:download")
|
||||
public R downloadFiles(HttpServletResponse response) throws IOException { |
||||
questionsService.downloadFiles(response); |
||||
return R.ok(); |
||||
} |
||||
|
||||
@Override |
||||
@GetMapping("/evaluation") |
||||
public R evaluation() { |
||||
EvaluationVO evaluation = questionsService.evaluation(); |
||||
return R.ok().put("data", evaluation); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,17 @@ |
||||
package com.msdw.tms.dao; |
||||
|
||||
import com.msdw.tms.entity.EvaluationRulesEntity; |
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
import org.apache.ibatis.annotations.Mapper; |
||||
|
||||
/** |
||||
* 测评规则信息记录,只记录一条信息 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-19 09:28:06 |
||||
*/ |
||||
@Mapper |
||||
public interface EvaluationRulesDao extends BaseMapper<EvaluationRulesEntity> { |
||||
|
||||
} |
@ -0,0 +1,17 @@ |
||||
package com.msdw.tms.dao; |
||||
|
||||
import com.msdw.tms.entity.QuestionsEntity; |
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
import org.apache.ibatis.annotations.Mapper; |
||||
|
||||
/** |
||||
* 记录试题信息 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-19 09:28:06 |
||||
*/ |
||||
@Mapper |
||||
public interface QuestionsDao extends BaseMapper<QuestionsEntity> { |
||||
|
||||
} |
@ -0,0 +1,17 @@ |
||||
package com.msdw.tms.dao; |
||||
|
||||
import com.msdw.tms.entity.XlsxTemplateEntity; |
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
import org.apache.ibatis.annotations.Mapper; |
||||
|
||||
/** |
||||
* 模板文件信息记录 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-19 09:28:06 |
||||
*/ |
||||
@Mapper |
||||
public interface XlsxTemplateDao extends BaseMapper<XlsxTemplateEntity> { |
||||
|
||||
} |
@ -0,0 +1,64 @@ |
||||
package com.msdw.tms.entity; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.Date; |
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* 测评规则信息记录,只记录一条信息 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-19 09:28:06 |
||||
*/ |
||||
@Data |
||||
@TableName("tms_evaluation_rules") |
||||
public class EvaluationRulesEntity implements Serializable { |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
/** |
||||
* 主键 |
||||
*/ |
||||
@TableId |
||||
private Integer id; |
||||
/** |
||||
* 测评类型:1:随机类型,0:自定义类型 |
||||
*/ |
||||
private Integer evaluationType; |
||||
/** |
||||
* 测评时长,单位:分钟 |
||||
*/ |
||||
private Integer duration; |
||||
/** |
||||
* 测评总题数 |
||||
*/ |
||||
private Integer questionNum; |
||||
/** |
||||
* 单选题数 |
||||
*/ |
||||
private Integer singleNum; |
||||
/** |
||||
* 只在类型为自定义类型时才启用:1:启用,0:不启用,默认1启用 |
||||
*/ |
||||
private Integer isSingleEnable; |
||||
/** |
||||
* 多选题数 |
||||
*/ |
||||
private Integer multipleNum; |
||||
/** |
||||
* 只在类型为自定义类型时才启用:1:启用,0:不启用,默认1启用 |
||||
*/ |
||||
private Integer isMultipleEnable; |
||||
/** |
||||
* 判断题数 |
||||
*/ |
||||
private Integer judgmentNum; |
||||
/** |
||||
* 只在类型为自定义类型时才启用:1:启用,0:不启用,默认1启用 |
||||
*/ |
||||
private Integer isJudgmentEnable; |
||||
|
||||
} |
@ -0,0 +1,100 @@ |
||||
package com.msdw.tms.entity; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.Date; |
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* 记录试题信息 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-19 09:28:06 |
||||
*/ |
||||
@Data |
||||
@TableName("tms_questions") |
||||
public class QuestionsEntity implements Serializable { |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
/** |
||||
* 自增主键 |
||||
*/ |
||||
@TableId |
||||
private Integer id; |
||||
/** |
||||
* 题型号:用于区分是什么题型 |
||||
*/ |
||||
private Integer questionTypeNo; |
||||
/** |
||||
* 题型名称 |
||||
*/ |
||||
private String questionType; |
||||
/** |
||||
* 题干信息 |
||||
*/ |
||||
private String questionStem; |
||||
/** |
||||
* A选项内容 |
||||
*/ |
||||
private String optionA; |
||||
/** |
||||
* B选项内容 |
||||
*/ |
||||
private String optionB; |
||||
/** |
||||
* C选项内容 |
||||
*/ |
||||
private String optionC; |
||||
/** |
||||
* D选项内容 |
||||
*/ |
||||
private String optionD; |
||||
/** |
||||
* E选项内容 |
||||
*/ |
||||
private String optionE; |
||||
/** |
||||
* F选项内容 |
||||
*/ |
||||
private String optionF; |
||||
/** |
||||
* 正确答案 |
||||
*/ |
||||
private String answer; |
||||
/** |
||||
* 答案解析 |
||||
*/ |
||||
private String answerAnalysis; |
||||
/** |
||||
* 是否禁用:1:启用,0:禁用,默认是1启用 |
||||
*/ |
||||
private Integer isEnable; |
||||
/** |
||||
* 是否删除:1使用,0删除,默认1使用 |
||||
*/ |
||||
private Integer isDel; |
||||
/** |
||||
* 创建人 |
||||
*/ |
||||
private String createUser; |
||||
/** |
||||
* 创建时间 |
||||
*/ |
||||
private Date createTime; |
||||
/** |
||||
* 修改人 |
||||
*/ |
||||
private String modifyUser; |
||||
/** |
||||
* 修改时间,用于排序,创建时,修改时间等于创建时间 |
||||
*/ |
||||
private Date modifyTime; |
||||
/** |
||||
* 试题科目 |
||||
*/ |
||||
private String subjects; |
||||
|
||||
} |
@ -0,0 +1,40 @@ |
||||
package com.msdw.tms.entity; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.Date; |
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* 模板文件信息记录 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-19 09:28:06 |
||||
*/ |
||||
@Data |
||||
@TableName("tms_xlsx_template") |
||||
public class XlsxTemplateEntity implements Serializable { |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
/** |
||||
* 主键 |
||||
*/ |
||||
@TableId |
||||
private Integer id; |
||||
/** |
||||
* 文件名 |
||||
*/ |
||||
private String fileName; |
||||
/** |
||||
* 文件全路径 |
||||
*/ |
||||
private String fileUrl; |
||||
/** |
||||
* 状态 |
||||
*/ |
||||
private Integer status; |
||||
|
||||
} |
@ -0,0 +1,61 @@ |
||||
package com.msdw.tms.entity.request; |
||||
|
||||
import lombok.Data; |
||||
|
||||
import java.util.Date; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 试题的基本信息表 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-14 16:05:06 |
||||
*/ |
||||
@Data |
||||
public class QuestionsAddRequest { |
||||
/** |
||||
* 题型名称 |
||||
*/ |
||||
private String questionType; |
||||
/** |
||||
* 题干信息 |
||||
*/ |
||||
private String questionStem; |
||||
/** |
||||
* A选项内容 |
||||
*/ |
||||
private String optionA; |
||||
/** |
||||
* B选项内容 |
||||
*/ |
||||
private String optionB; |
||||
/** |
||||
* C选项内容 |
||||
*/ |
||||
private String optionC; |
||||
/** |
||||
* D选项内容 |
||||
*/ |
||||
private String optionD; |
||||
/** |
||||
* E选项内容 |
||||
*/ |
||||
private String optionE; |
||||
/** |
||||
* F选项内容 |
||||
*/ |
||||
private String optionF; |
||||
/** |
||||
* 正确答案 |
||||
*/ |
||||
private String answer; |
||||
/** |
||||
* 答案解析 |
||||
*/ |
||||
private String answerAnalysis; |
||||
/** |
||||
* 试题科目 |
||||
*/ |
||||
private String subjects; |
||||
} |
@ -0,0 +1,70 @@ |
||||
package com.msdw.tms.entity.request; |
||||
|
||||
import com.msdw.tms.common.utils.poi.ExcelAttribute; |
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* 试题的基本信息表 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-14 16:05:06 |
||||
*/ |
||||
@Data |
||||
public class QuestionsImportRequest { |
||||
/** |
||||
* 试题科目 |
||||
*/ |
||||
@ExcelAttribute(sort = 0) |
||||
private String subjects; |
||||
/** |
||||
* 题干,问题描述 |
||||
*/ |
||||
@ExcelAttribute(sort = 1) |
||||
private String questionStem; |
||||
/** |
||||
* 题型 |
||||
*/ |
||||
@ExcelAttribute(sort = 2) |
||||
private String questionType; |
||||
/** |
||||
* 选项A |
||||
*/ |
||||
@ExcelAttribute(sort = 3) |
||||
private String optionA; |
||||
/** |
||||
* 选项B |
||||
*/ |
||||
@ExcelAttribute(sort = 4) |
||||
private String optionB; |
||||
/** |
||||
* 选项C |
||||
*/ |
||||
@ExcelAttribute(sort = 5) |
||||
private String optionC; |
||||
/** |
||||
* 选项D |
||||
*/ |
||||
@ExcelAttribute(sort = 6) |
||||
private String optionD; |
||||
/** |
||||
* 选项E |
||||
*/ |
||||
@ExcelAttribute(sort = 7) |
||||
private String optionE; |
||||
/** |
||||
* 选项F |
||||
*/ |
||||
@ExcelAttribute(sort = 8) |
||||
private String optionF; |
||||
/** |
||||
* 正确答案 |
||||
*/ |
||||
@ExcelAttribute(sort = 9) |
||||
private String answer; |
||||
/** |
||||
* 答案解析 |
||||
*/ |
||||
@ExcelAttribute(sort = 10) |
||||
private String answerAnalysis; |
||||
} |
@ -0,0 +1,36 @@ |
||||
package com.msdw.tms.entity.request; |
||||
|
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* 试题的基本信息表 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-14 16:05:06 |
||||
*/ |
||||
@Data |
||||
public class QuestionsQueryRequest { |
||||
|
||||
/** |
||||
* 题干,问题描述 |
||||
*/ |
||||
private String questionStem; |
||||
|
||||
// /**
|
||||
// * 题型id
|
||||
// */
|
||||
// private Integer questionType;
|
||||
// /**
|
||||
// * 参考答案
|
||||
// */
|
||||
// private String answer;
|
||||
// /**
|
||||
// * 答案解析
|
||||
// */
|
||||
// private String answerAnalysis;
|
||||
// /**
|
||||
// * 创建时,修改时间即为创建时间,修改时间用于前端显示和排序
|
||||
// */
|
||||
// private Date modifyTime;
|
||||
} |
@ -0,0 +1,62 @@ |
||||
package com.msdw.tms.entity.request; |
||||
|
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* 试题的基本信息表 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-14 16:05:06 |
||||
*/ |
||||
@Data |
||||
public class QuestionsUpdateRequest { |
||||
/** |
||||
* 主键 |
||||
*/ |
||||
private Integer id; |
||||
/** |
||||
* 题型名称 |
||||
*/ |
||||
private String questionType; |
||||
/** |
||||
* 题干信息 |
||||
*/ |
||||
private String questionStem; |
||||
/** |
||||
* A选项内容 |
||||
*/ |
||||
private String optionA; |
||||
/** |
||||
* B选项内容 |
||||
*/ |
||||
private String optionB; |
||||
/** |
||||
* C选项内容 |
||||
*/ |
||||
private String optionC; |
||||
/** |
||||
* D选项内容 |
||||
*/ |
||||
private String optionD; |
||||
/** |
||||
* E选项内容 |
||||
*/ |
||||
private String optionE; |
||||
/** |
||||
* F选项内容 |
||||
*/ |
||||
private String optionF; |
||||
/** |
||||
* 正确答案 |
||||
*/ |
||||
private String answer; |
||||
/** |
||||
* 答案解析 |
||||
*/ |
||||
private String answerAnalysis; |
||||
/** |
||||
* 试题科目 |
||||
*/ |
||||
private String subjects; |
||||
} |
@ -0,0 +1,54 @@ |
||||
package com.msdw.tms.entity.response; |
||||
|
||||
import lombok.ToString; |
||||
|
||||
/** |
||||
* @Author: mrt. |
||||
* @Description: |
||||
* @Date:Created in 2018/1/24 18:33. |
||||
* @Modified By: |
||||
*/ |
||||
|
||||
@ToString |
||||
public enum CommonCode implements ResultCode { |
||||
|
||||
SUCCESS(true, 10000, "操作成功!"), |
||||
UNAUTHENTICATED(false, 10001, "此操作需要登陆系统!"), |
||||
UNAUTHORISE(false, 10002, "权限不足,无权操作!"), |
||||
INVALID_PARAM(false, 10003, "非法参数!"), |
||||
QUESTION_NUM_INVALID(false, 10004, "测评题目数量设置超出范围!"), |
||||
QUESTION_EXISTS(false, 10005, "此题目已存在!"), |
||||
QUESTIONTYPE_INVALID(false, 10005, "题型错误!"), |
||||
FAIL(false, 11111, "操作失败!"), |
||||
SERVER_ERROR(false, 99999, "抱歉,系统繁忙,请稍后重试!"); |
||||
// private static ImmutableMap<Integer, CommonCode> codes ;
|
||||
//操作是否成功
|
||||
boolean success; |
||||
//操作代码
|
||||
int code; |
||||
//提示信息
|
||||
String message; |
||||
|
||||
private CommonCode(boolean success, int code, String message) { |
||||
this.success = success; |
||||
this.code = code; |
||||
this.message = message; |
||||
} |
||||
|
||||
@Override |
||||
public boolean success() { |
||||
return success; |
||||
} |
||||
|
||||
@Override |
||||
public int code() { |
||||
return code; |
||||
} |
||||
|
||||
@Override |
||||
public String message() { |
||||
return message; |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,9 @@ |
||||
package com.msdw.tms.entity.response; |
||||
|
||||
/** |
||||
* Created by admin on 2018/3/5. |
||||
*/ |
||||
public interface Response { |
||||
public static final boolean SUCCESS = true; |
||||
public static final int SUCCESS_CODE = 10000; |
||||
} |
@ -0,0 +1,41 @@ |
||||
package com.msdw.tms.entity.response; |
||||
|
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
import lombok.ToString; |
||||
|
||||
/** |
||||
* @Author: mrt. |
||||
* @Description: |
||||
* @Date:Created in 2018/1/24 18:33. |
||||
* @Modified By: |
||||
*/ |
||||
@Data |
||||
@ToString |
||||
@NoArgsConstructor |
||||
public class ResponseResult implements Response { |
||||
|
||||
//操作是否成功
|
||||
boolean success = SUCCESS; |
||||
|
||||
//操作代码
|
||||
int code = SUCCESS_CODE; |
||||
|
||||
//提示信息
|
||||
String message; |
||||
|
||||
public ResponseResult(ResultCode resultCode) { |
||||
this.success = resultCode.success(); |
||||
this.code = resultCode.code(); |
||||
this.message = resultCode.message(); |
||||
} |
||||
|
||||
public static ResponseResult SUCCESS() { |
||||
return new ResponseResult(CommonCode.SUCCESS); |
||||
} |
||||
|
||||
public static ResponseResult FAIL() { |
||||
return new ResponseResult(CommonCode.FAIL); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,21 @@ |
||||
package com.msdw.tms.entity.response; |
||||
|
||||
/** |
||||
* Created by mrt on 2018/3/5. |
||||
* 10000-- 通用错误代码 |
||||
* 22000-- 媒资错误代码 |
||||
* 23000-- 用户中心错误代码 |
||||
* 24000-- cms错误代码 |
||||
* 25000-- 文件系统 |
||||
*/ |
||||
public interface ResultCode { |
||||
//操作是否成功,true为成功,false操作失败
|
||||
boolean success(); |
||||
|
||||
//操作代码
|
||||
int code(); |
||||
|
||||
//提示信息
|
||||
String message(); |
||||
|
||||
} |
@ -0,0 +1,76 @@ |
||||
package com.msdw.tms.entity.vo; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.Data; |
||||
|
||||
import java.io.Serializable; |
||||
|
||||
/** |
||||
* 测评规则信息记录,只记录一条信息 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-19 09:28:06 |
||||
*/ |
||||
@Data |
||||
public class EvaluationRulesVO implements Serializable { |
||||
|
||||
/** |
||||
* 主键 |
||||
*/ |
||||
private Integer id; |
||||
/** |
||||
* 测评类型:1:随机类型,0:自定义类型 |
||||
*/ |
||||
private Integer evaluationType; |
||||
/** |
||||
* 测评时长,单位:分钟 |
||||
*/ |
||||
private Integer duration; |
||||
/** |
||||
* 测评总题数 |
||||
*/ |
||||
private Integer questionNum; |
||||
/** |
||||
* 题库总题数 |
||||
*/ |
||||
private Integer totalQuestionNum; |
||||
/** |
||||
* 单选题数 |
||||
*/ |
||||
private Integer singleNum; |
||||
/** |
||||
* 题库单选题总数 |
||||
*/ |
||||
private Integer totalSingleNum; |
||||
/** |
||||
* 只在类型为自定义类型时才启用:1:启用,0:不启用,默认1启用 |
||||
*/ |
||||
private Integer isSingleEnable; |
||||
/** |
||||
* 多选题数 |
||||
*/ |
||||
private Integer multipleNum; |
||||
/** |
||||
* 题库多选题总数 |
||||
*/ |
||||
private Integer totalMultipleNum; |
||||
/** |
||||
* 只在类型为自定义类型时才启用:1:启用,0:不启用,默认1启用 |
||||
*/ |
||||
private Integer isMultipleEnable; |
||||
/** |
||||
* 判断题数 |
||||
*/ |
||||
private Integer judgmentNum; |
||||
/** |
||||
* 题库判断题总数 |
||||
*/ |
||||
private Integer totalJudgmentNum; |
||||
/** |
||||
* 只在类型为自定义类型时才启用:1:启用,0:不启用,默认1启用 |
||||
*/ |
||||
private Integer isJudgmentEnable; |
||||
|
||||
} |
@ -0,0 +1,66 @@ |
||||
package com.msdw.tms.entity.vo; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import com.msdw.tms.entity.QuestionsEntity; |
||||
import lombok.Data; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* 测评规则信息记录,只记录一条信息 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-19 09:28:06 |
||||
*/ |
||||
@Data |
||||
@TableName("tms_evaluation_rules") |
||||
public class EvaluationVO implements Serializable { |
||||
|
||||
/** |
||||
* 主键 |
||||
*/ |
||||
private Integer id; |
||||
/** |
||||
* 测评类型:1:随机类型,0:自定义类型 |
||||
*/ |
||||
private Integer evaluationType; |
||||
/** |
||||
* 测评时长,单位:分钟 |
||||
*/ |
||||
private Integer duration; |
||||
/** |
||||
* 测评总题数 |
||||
*/ |
||||
private Integer questionNum; |
||||
/** |
||||
* 单选题数 |
||||
*/ |
||||
private Integer singleNum; |
||||
/** |
||||
* 只在类型为自定义类型时才启用:1:启用,0:不启用,默认1启用 |
||||
*/ |
||||
private Integer isSingleEnable; |
||||
/** |
||||
* 多选题数 |
||||
*/ |
||||
private Integer multipleNum; |
||||
/** |
||||
* 只在类型为自定义类型时才启用:1:启用,0:不启用,默认1启用 |
||||
*/ |
||||
private Integer isMultipleEnable; |
||||
/** |
||||
* 判断题数 |
||||
*/ |
||||
private Integer judgmentNum; |
||||
/** |
||||
* 只在类型为自定义类型时才启用:1:启用,0:不启用,默认1启用 |
||||
*/ |
||||
private Integer isJudgmentEnable; |
||||
/** |
||||
*试题列表 |
||||
*/ |
||||
private Set<QuestionsEntity> Questions; |
||||
} |
@ -0,0 +1,121 @@ |
||||
package com.msdw.tms.entity.vo; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.Data; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* 记录试题信息 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-19 09:28:06 |
||||
*/ |
||||
@Data |
||||
public class QuestionsDetailVO implements Serializable { |
||||
|
||||
/** |
||||
* 主键 |
||||
*/ |
||||
private Integer id; |
||||
/** |
||||
* 题型号:用于区分是什么题型 |
||||
*/ |
||||
private Integer questionTypeNo; |
||||
/** |
||||
* 题型名称 |
||||
*/ |
||||
private String questionType; |
||||
/** |
||||
* 题干信息 |
||||
*/ |
||||
private String questionStem; |
||||
/** |
||||
* A选项内容 |
||||
*/ |
||||
private String optionA; |
||||
/** |
||||
* A选项是否为正确答案 |
||||
*/ |
||||
private boolean AIsTrue = false; |
||||
/** |
||||
* B选项内容 |
||||
*/ |
||||
private String optionB; |
||||
/** |
||||
* B选项是否为正确答案 |
||||
*/ |
||||
private boolean BIsTrue = false; |
||||
/** |
||||
* C选项内容 |
||||
*/ |
||||
private String optionC; |
||||
/** |
||||
* C选项是否为正确答案 |
||||
*/ |
||||
private boolean CIsTrue = false; |
||||
/** |
||||
* D选项内容 |
||||
*/ |
||||
private String optionD; |
||||
/** |
||||
* D选项是否为正确答案 |
||||
*/ |
||||
private boolean DIsTrue = false; |
||||
/** |
||||
* E选项内容 |
||||
*/ |
||||
private String optionE; |
||||
/** |
||||
* E选项是否为正确答案 |
||||
*/ |
||||
private boolean EIsTrue = false; |
||||
/** |
||||
* F选项内容 |
||||
*/ |
||||
private String optionF; |
||||
/** |
||||
* F选项是否为正确答案 |
||||
*/ |
||||
private boolean FIsTrue = false; |
||||
/** |
||||
* 正确答案 |
||||
*/ |
||||
private String answer; |
||||
/** |
||||
* 答案解析 |
||||
*/ |
||||
private String answerAnalysis; |
||||
/** |
||||
* 是否禁用:1:启用,0:禁用,默认是1启用 |
||||
*/ |
||||
private Integer isEnable; |
||||
/** |
||||
* 是否删除:1使用,0删除,默认1使用 |
||||
*/ |
||||
private Integer isDel; |
||||
/** |
||||
* 创建人 |
||||
*/ |
||||
private String createUser; |
||||
/** |
||||
* 创建时间 |
||||
*/ |
||||
private Date createTime; |
||||
/** |
||||
* 修改人 |
||||
*/ |
||||
private String modifyUser; |
||||
/** |
||||
* 修改时间,用于排序,创建时,修改时间等于创建时间 |
||||
*/ |
||||
private Date modifyTime; |
||||
/** |
||||
* 试题科目 |
||||
*/ |
||||
private String subjects; |
||||
|
||||
} |
@ -0,0 +1,32 @@ |
||||
package com.msdw.tms.service; |
||||
|
||||
import com.msdw.tms.common.utils.FilesResult; |
||||
import org.springframework.web.multipart.MultipartFile; |
||||
|
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.IOException; |
||||
|
||||
public interface AliyunOssService { |
||||
|
||||
/** |
||||
* 上传文件 |
||||
* |
||||
* @param file 上传文件 |
||||
*/ |
||||
FilesResult uploadFiles(MultipartFile file) throws IOException; |
||||
|
||||
/** |
||||
* 下载文件 |
||||
* |
||||
* @param response |
||||
* @param objectName 本地路径 |
||||
*/ |
||||
void downloadFiles(HttpServletResponse response, String objectName) throws IOException; |
||||
|
||||
/** |
||||
* 根据文件路径+文件名称,删除该文件 |
||||
* |
||||
* @param filename |
||||
*/ |
||||
void deleteFile(String filename); |
||||
} |
@ -0,0 +1,19 @@ |
||||
package com.msdw.tms.service; |
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService; |
||||
import com.msdw.tms.entity.EvaluationRulesEntity; |
||||
import com.msdw.tms.entity.vo.EvaluationRulesVO; |
||||
|
||||
/** |
||||
* 测评规则信息记录,只记录一条信息 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-19 09:28:06 |
||||
*/ |
||||
public interface EvaluationRulesService extends IService<EvaluationRulesEntity> { |
||||
EvaluationRulesVO getEvaluationRules(); |
||||
|
||||
boolean updateEvaluationRulesById(EvaluationRulesEntity evaluationRules); |
||||
} |
||||
|
@ -0,0 +1,48 @@ |
||||
package com.msdw.tms.service; |
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService; |
||||
import com.msdw.tms.common.utils.FilesResult; |
||||
import com.msdw.tms.common.utils.PageUtils; |
||||
import com.msdw.tms.entity.QuestionsEntity; |
||||
import com.msdw.tms.entity.request.QuestionsAddRequest; |
||||
import com.msdw.tms.entity.request.QuestionsQueryRequest; |
||||
import com.msdw.tms.entity.request.QuestionsUpdateRequest; |
||||
import com.msdw.tms.entity.vo.EvaluationVO; |
||||
import com.msdw.tms.entity.vo.QuestionsDetailVO; |
||||
import org.springframework.web.multipart.MultipartFile; |
||||
|
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.IOException; |
||||
import java.util.List; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* 记录试题信息 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-19 09:28:06 |
||||
*/ |
||||
public interface QuestionsService extends IService<QuestionsEntity> { |
||||
|
||||
PageUtils queryQuestionsPage(Integer page, Integer size, QuestionsQueryRequest request); |
||||
|
||||
QuestionsDetailVO getQuestionDetailById(Integer id); |
||||
|
||||
boolean saveQuestion(QuestionsAddRequest questions); |
||||
|
||||
boolean updateQuestionById(QuestionsUpdateRequest questions); |
||||
|
||||
boolean isnable(Integer id); |
||||
|
||||
boolean deleteByIds(List<Integer> asList); |
||||
|
||||
boolean importQuestion(MultipartFile file) throws IOException; |
||||
|
||||
FilesResult uploadFiles(MultipartFile file) throws IOException; |
||||
|
||||
void downloadFiles(HttpServletResponse response) throws IOException; |
||||
|
||||
EvaluationVO evaluation(); |
||||
} |
||||
|
@ -0,0 +1,15 @@ |
||||
package com.msdw.tms.service; |
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService; |
||||
import com.msdw.tms.entity.XlsxTemplateEntity; |
||||
|
||||
/** |
||||
* 模板文件信息记录 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-08-19 09:28:06 |
||||
*/ |
||||
public interface XlsxTemplateService extends IService<XlsxTemplateEntity> { |
||||
} |
||||
|
@ -0,0 +1,58 @@ |
||||
package com.msdw.tms.service.impl; |
||||
|
||||
import com.aliyun.oss.OSSClient; |
||||
import com.msdw.tms.common.utils.AliyunOssUtil; |
||||
import com.msdw.tms.common.utils.FilesResult; |
||||
import com.msdw.tms.config.AliyunOssConfig; |
||||
import com.msdw.tms.service.AliyunOssService; |
||||
import org.springframework.beans.factory.BeanFactory; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
import org.springframework.web.multipart.MultipartFile; |
||||
|
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* 阿里云OSSUtil |
||||
*/ |
||||
@Service |
||||
public class AliyunOssServiceImpl implements AliyunOssService { |
||||
|
||||
@Autowired |
||||
private AliyunOssConfig config; |
||||
|
||||
@Autowired |
||||
private BeanFactory beanFactory; |
||||
|
||||
/** |
||||
* 上传文件 |
||||
* |
||||
* @param file 上传文件 |
||||
*/ |
||||
public FilesResult uploadFiles(MultipartFile file) throws IOException { |
||||
OSSClient client = beanFactory.getBean(OSSClient.class); |
||||
return AliyunOssUtil.uploadFiles(file, client, config); |
||||
} |
||||
|
||||
/** |
||||
* 下载文件 |
||||
* |
||||
* @param response |
||||
* @param objectName 本地路径 |
||||
*/ |
||||
public void downloadFiles(HttpServletResponse response, String objectName) throws IOException { |
||||
OSSClient client = beanFactory.getBean(OSSClient.class); |
||||
AliyunOssUtil.downloadFiles(response, client, config, objectName); |
||||
} |
||||
|
||||
/** |
||||
* 根据文件路径+文件名称,删除该文件 |
||||
* |
||||
* @param filename |
||||
*/ |
||||
public void deleteFile(String filename) { |
||||
OSSClient client = beanFactory.getBean(OSSClient.class); |
||||
AliyunOssUtil.deleteFile(client, config.getBucketName(), filename); |
||||
} |
||||
} |
@ -0,0 +1,116 @@ |
||||
package com.msdw.tms.service.impl; |
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
||||
import com.msdw.tms.common.exception.ExceptionCast; |
||||
import com.msdw.tms.common.utils.Constant; |
||||
import com.msdw.tms.dao.EvaluationRulesDao; |
||||
import com.msdw.tms.entity.EvaluationRulesEntity; |
||||
import com.msdw.tms.entity.QuestionsEntity; |
||||
import com.msdw.tms.entity.response.CommonCode; |
||||
import com.msdw.tms.entity.vo.EvaluationRulesVO; |
||||
import com.msdw.tms.service.EvaluationRulesService; |
||||
import com.msdw.tms.service.QuestionsService; |
||||
import org.springframework.beans.BeanUtils; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
|
||||
@Service("evaluationRulesService") |
||||
public class EvaluationRulesServiceImpl extends ServiceImpl<EvaluationRulesDao, EvaluationRulesEntity> implements EvaluationRulesService { |
||||
|
||||
@Autowired |
||||
QuestionsService questionsService; |
||||
|
||||
@Override |
||||
public EvaluationRulesVO getEvaluationRules() { |
||||
EvaluationRulesVO evaluationRulesVO = new EvaluationRulesVO(); |
||||
|
||||
EvaluationRulesEntity evaluationRules = this.getById(Constant.EVALUATION_RULES_ID); |
||||
|
||||
if (evaluationRules.getEvaluationType() == Constant.RulesType.CUSTOMIZE.getType()) {//自定义
|
||||
|
||||
int totalNum = 0; |
||||
if (evaluationRules.getIsSingleEnable() == Constant.IsEnable.ENABLE.getType()) {//启用
|
||||
totalNum += evaluationRules.getSingleNum(); |
||||
} |
||||
if (evaluationRules.getIsMultipleEnable() == Constant.IsEnable.ENABLE.getType()) {//启用
|
||||
totalNum += evaluationRules.getMultipleNum(); |
||||
} |
||||
if (evaluationRules.getIsJudgmentEnable() == Constant.IsEnable.ENABLE.getType()) {//启用
|
||||
totalNum += evaluationRules.getJudgmentNum(); |
||||
} |
||||
|
||||
//类型为自定义,测评试题数量是各个参与测评的试题类型数量之和
|
||||
evaluationRules.setQuestionNum(totalNum); |
||||
} |
||||
|
||||
BeanUtils.copyProperties(evaluationRules, evaluationRulesVO); |
||||
|
||||
QueryWrapper<QuestionsEntity> queryWrapper = new QueryWrapper<>(); |
||||
queryWrapper.eq("is_del", Constant.IsDel.NOT_DEL.getType()) //未删除
|
||||
.eq("is_enable", Constant.IsEnable.ENABLE.getType()); //启用
|
||||
|
||||
evaluationRulesVO.setTotalQuestionNum(questionsService.count(queryWrapper));//总题数
|
||||
|
||||
int totalSingleNum = questionsService.count(queryWrapper.eq("question_type_no", |
||||
Constant.QuestionType.SINGLE_CHOICE.getType()));//单选题总数
|
||||
int totalMultipleNum = questionsService.count(queryWrapper.eq("question_type_no", |
||||
Constant.QuestionType.MULTIPLE_CHOICE.getType()));//多选题总数
|
||||
int totalJudgmentNum = questionsService.count(queryWrapper.eq("question_type_no", |
||||
Constant.QuestionType.TRUE_OR_FALSE.getType()));//判断题总数
|
||||
|
||||
evaluationRulesVO.setTotalSingleNum(totalSingleNum); |
||||
evaluationRulesVO.setTotalMultipleNum(totalMultipleNum); |
||||
evaluationRulesVO.setTotalJudgmentNum(totalJudgmentNum); |
||||
|
||||
return evaluationRulesVO; |
||||
} |
||||
|
||||
@Override |
||||
public boolean updateEvaluationRulesById(EvaluationRulesEntity evaluationRules) { |
||||
QueryWrapper<QuestionsEntity> queryWrapper = new QueryWrapper<>(); |
||||
queryWrapper.eq("is_del", Constant.IsDel.NOT_DEL.getType()) //未删除
|
||||
.eq("is_enable", Constant.IsEnable.ENABLE.getType()); //启用
|
||||
|
||||
//判断题目是否超出范围
|
||||
//判断类型
|
||||
Integer evaluationType = evaluationRules.getEvaluationType(); |
||||
if (evaluationType == Constant.RulesType.RANDOM.getType()) {//随机
|
||||
Integer questionNum = evaluationRules.getQuestionNum(); |
||||
|
||||
//查询总题数
|
||||
int count = questionsService.count(queryWrapper);//总题数
|
||||
numIncalid(questionNum, count); |
||||
|
||||
} else if (evaluationType == Constant.RulesType.CUSTOMIZE.getType()) {//自定义
|
||||
if (evaluationRules.getIsSingleEnable() == Constant.IsEnable.ENABLE.getType()) {//启用
|
||||
int singleNum = evaluationRules.getSingleNum(); |
||||
int totalSingleNum = questionsService.count(queryWrapper.eq("question_type_no", |
||||
Constant.QuestionType.SINGLE_CHOICE.getType()));//单选题总数
|
||||
numIncalid(singleNum, totalSingleNum); |
||||
} |
||||
if (evaluationRules.getIsMultipleEnable() == Constant.IsEnable.ENABLE.getType()) {//启用
|
||||
int multipleNum = evaluationRules.getMultipleNum(); |
||||
int totalMultipleNum = questionsService.count(queryWrapper.eq("question_type_no", |
||||
Constant.QuestionType.MULTIPLE_CHOICE.getType()));//多选题总数
|
||||
numIncalid(multipleNum, totalMultipleNum); |
||||
} |
||||
if (evaluationRules.getIsJudgmentEnable() == Constant.IsEnable.ENABLE.getType()) {//启用
|
||||
int judgmentNum = evaluationRules.getJudgmentNum(); |
||||
int totalJudgmentNum = questionsService.count(queryWrapper.eq("question_type_no", |
||||
Constant.QuestionType.TRUE_OR_FALSE.getType()));//判断题总数
|
||||
numIncalid(judgmentNum, totalJudgmentNum); |
||||
} |
||||
|
||||
} |
||||
|
||||
return this.updateById(evaluationRules); |
||||
} |
||||
|
||||
private void numIncalid(int num, int totalNum) { |
||||
if (num < 0 || num > totalNum) { |
||||
ExceptionCast.cast(CommonCode.QUESTION_NUM_INVALID); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,404 @@ |
||||
package com.msdw.tms.service.impl; |
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
||||
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
||||
import com.msdw.tms.common.exception.ExceptionCast; |
||||
import com.msdw.tms.common.utils.Constant; |
||||
import com.msdw.tms.common.utils.FilesResult; |
||||
import com.msdw.tms.common.utils.PageUtils; |
||||
import com.msdw.tms.common.utils.Query; |
||||
import com.msdw.tms.common.utils.poi.ExcelImportUtil; |
||||
import com.msdw.tms.dao.QuestionsDao; |
||||
import com.msdw.tms.entity.QuestionsEntity; |
||||
import com.msdw.tms.entity.XlsxTemplateEntity; |
||||
import com.msdw.tms.entity.request.QuestionsAddRequest; |
||||
import com.msdw.tms.entity.request.QuestionsImportRequest; |
||||
import com.msdw.tms.entity.request.QuestionsQueryRequest; |
||||
import com.msdw.tms.entity.request.QuestionsUpdateRequest; |
||||
import com.msdw.tms.entity.response.CommonCode; |
||||
import com.msdw.tms.entity.vo.EvaluationRulesVO; |
||||
import com.msdw.tms.entity.vo.EvaluationVO; |
||||
import com.msdw.tms.entity.vo.QuestionsDetailVO; |
||||
import com.msdw.tms.service.AliyunOssService; |
||||
import com.msdw.tms.service.EvaluationRulesService; |
||||
import com.msdw.tms.service.QuestionsService; |
||||
import com.msdw.tms.service.XlsxTemplateService; |
||||
import org.apache.commons.lang.StringUtils; |
||||
import org.springframework.beans.BeanUtils; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
import org.springframework.transaction.annotation.Transactional; |
||||
import org.springframework.web.multipart.MultipartFile; |
||||
|
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.IOException; |
||||
import java.util.*; |
||||
import java.util.stream.Collectors; |
||||
|
||||
|
||||
@Service("questionsService") |
||||
public class QuestionsServiceImpl extends ServiceImpl<QuestionsDao, QuestionsEntity> implements QuestionsService { |
||||
|
||||
@Autowired |
||||
private AliyunOssService ossService; |
||||
|
||||
@Autowired |
||||
XlsxTemplateService xlsxTemplateService; |
||||
|
||||
@Autowired |
||||
EvaluationRulesService evaluationRulesService; |
||||
|
||||
/** |
||||
* 条件加分页查询,题干模糊查询,未删除,修改时间降序 |
||||
* |
||||
* @param page |
||||
* @param size |
||||
* @param request |
||||
* @return |
||||
*/ |
||||
@Override |
||||
public PageUtils queryQuestionsPage(Integer page, Integer size, QuestionsQueryRequest request) { |
||||
//请求包装类
|
||||
QueryWrapper<QuestionsEntity> queryWrapper = new QueryWrapper<>(); |
||||
|
||||
//只查询未被删除的试题
|
||||
queryWrapper.eq("is_del", Constant.IsDel.NOT_DEL.getType()); |
||||
|
||||
//判断请求体是否为空
|
||||
if (request != null) { |
||||
// 题干:判断题干是否为空,不为空则加入搜索条件
|
||||
if (request.getQuestionStem() != null) { |
||||
queryWrapper.like("question_stem", request.getQuestionStem()); |
||||
} |
||||
// 题型:判断题型是否为空,不为空则加入搜索条件
|
||||
// if (questionsRequest.getQuestionType() != null) {
|
||||
// queryWrapper.eq("question_type", questionsRequest.getQuestionType());
|
||||
// }
|
||||
// 修改时间:判断修改时间是否为空,不为空则加入搜索条件
|
||||
// if (questionsRequest.getModifyTime() != null) {
|
||||
// queryWrapper.eq("modify_time", questionsRequest.getModifyTime());
|
||||
// }
|
||||
} |
||||
|
||||
//修改时间降序
|
||||
queryWrapper.orderByDesc("modify_time"); |
||||
|
||||
IPage<QuestionsEntity> questionsEntityIPage = this.page( |
||||
new Query<QuestionsEntity>().getPage(page, size), |
||||
queryWrapper |
||||
); |
||||
|
||||
return new PageUtils(questionsEntityIPage); |
||||
} |
||||
|
||||
@Override |
||||
public QuestionsDetailVO getQuestionDetailById(Integer id) { |
||||
{ |
||||
QuestionsDetailVO questionsDetailVO = new QuestionsDetailVO(); |
||||
//查询试题信息
|
||||
QuestionsEntity questionsEntity = this.getById(id); |
||||
BeanUtils.copyProperties(questionsEntity, questionsDetailVO); |
||||
//处理每个选项是否为被设置为答案
|
||||
String answer = questionsEntity.getAnswer(); |
||||
|
||||
if (answer.contains(Constant.A)) { |
||||
questionsDetailVO.setAIsTrue(true); |
||||
} |
||||
if (answer.contains(Constant.B)) { |
||||
questionsDetailVO.setBIsTrue(true); |
||||
} |
||||
if (answer.contains(Constant.C)) { |
||||
questionsDetailVO.setCIsTrue(true); |
||||
} |
||||
if (answer.contains(Constant.D)) { |
||||
questionsDetailVO.setDIsTrue(true); |
||||
} |
||||
if (answer.contains(Constant.E)) { |
||||
questionsDetailVO.setEIsTrue(true); |
||||
} |
||||
if (answer.contains(Constant.F)) { |
||||
questionsDetailVO.setFIsTrue(true); |
||||
} |
||||
return questionsDetailVO; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 保存试题,根据题型名称得到题型号,设置创建时间和修改时间 |
||||
* |
||||
* @param questions |
||||
* @return |
||||
*/ |
||||
@Override |
||||
@Transactional |
||||
public boolean saveQuestion(QuestionsAddRequest questions) { |
||||
if (questions == null || StringUtils.isEmpty(questions.getQuestionStem())) { |
||||
ExceptionCast.cast(CommonCode.INVALID_PARAM); |
||||
} |
||||
|
||||
// 判断是否题干重复。。。
|
||||
isStemRepeat(questions.getQuestionStem()); |
||||
|
||||
QuestionsEntity questionsEntity = new QuestionsEntity(); |
||||
BeanUtils.copyProperties(questions, questionsEntity); |
||||
|
||||
String questionType = questions.getQuestionType(); |
||||
//根据题型名称得到题型号
|
||||
if (questionType.equals(Constant.QuestionType.SINGLE_CHOICE.getDesc())) { |
||||
//单选题
|
||||
questionsEntity.setQuestionTypeNo(Constant.QuestionType.SINGLE_CHOICE.getType()); |
||||
} else if (questionType.equals(Constant.QuestionType.MULTIPLE_CHOICE.getDesc())) { |
||||
//多选题
|
||||
questionsEntity.setQuestionTypeNo(Constant.QuestionType.MULTIPLE_CHOICE.getType()); |
||||
} else if (questionType.equals(Constant.QuestionType.TRUE_OR_FALSE.getDesc())) { |
||||
//判断题
|
||||
questionsEntity.setQuestionTypeNo(Constant.QuestionType.TRUE_OR_FALSE.getType()); |
||||
} else {// 判断题型是否不存在。。。
|
||||
//说明题型不正确
|
||||
ExceptionCast.cast(CommonCode.QUESTIONTYPE_INVALID); |
||||
} |
||||
|
||||
questionsEntity.setCreateTime(new Date()); |
||||
questionsEntity.setModifyTime(new Date()); |
||||
//TODO 创建者和修改者。。。
|
||||
|
||||
return this.save(questionsEntity); |
||||
} |
||||
|
||||
@Override |
||||
@Transactional |
||||
public boolean updateQuestionById(QuestionsUpdateRequest questions) { |
||||
if (questions == null || questions.getId() == null || StringUtils.isEmpty(questions.getQuestionStem())) { |
||||
ExceptionCast.cast(CommonCode.INVALID_PARAM); |
||||
} |
||||
|
||||
// 判断是否题干重复
|
||||
isStemRepeat(questions.getQuestionStem()); |
||||
|
||||
// 判断id是否存在
|
||||
if (this.getById(questions.getId()) == null) { |
||||
ExceptionCast.cast(CommonCode.INVALID_PARAM); |
||||
} |
||||
|
||||
QuestionsEntity questionsEntity = new QuestionsEntity(); |
||||
BeanUtils.copyProperties(questions, questionsEntity); |
||||
|
||||
String questionType = questions.getQuestionType(); |
||||
//根据题型名称得到题型号
|
||||
if (questionType.equals(Constant.QuestionType.SINGLE_CHOICE.getDesc())) { |
||||
//单选题
|
||||
questionsEntity.setQuestionTypeNo(Constant.QuestionType.SINGLE_CHOICE.getType()); |
||||
} else if (questionType.equals(Constant.QuestionType.MULTIPLE_CHOICE.getDesc())) { |
||||
//多选题
|
||||
questionsEntity.setQuestionTypeNo(Constant.QuestionType.MULTIPLE_CHOICE.getType()); |
||||
} else if (questionType.equals(Constant.QuestionType.TRUE_OR_FALSE.getDesc())) { |
||||
//判断题
|
||||
questionsEntity.setQuestionTypeNo(Constant.QuestionType.TRUE_OR_FALSE.getType()); |
||||
} else { |
||||
//说明题型不正确
|
||||
ExceptionCast.cast(CommonCode.QUESTIONTYPE_INVALID); |
||||
} |
||||
|
||||
questionsEntity.setModifyTime(new Date()); |
||||
//TODO 设置修改者。。。
|
||||
|
||||
return this.updateById(questionsEntity); |
||||
} |
||||
|
||||
private void isStemRepeat(String stem) { |
||||
int count = this.count(new QueryWrapper<QuestionsEntity>().eq("question_stem", stem)); |
||||
if (count > 0) {//说明已存在
|
||||
//抛出题目已存在异常
|
||||
ExceptionCast.cast(CommonCode.QUESTION_EXISTS); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
@Transactional |
||||
public boolean isnable(Integer id) { |
||||
QuestionsEntity questionsEntity = new QuestionsEntity(); |
||||
questionsEntity.setId(id); |
||||
QuestionsEntity byId = this.getById(id); |
||||
if (byId.getIsEnable() == Constant.IsEnable.ENABLE.getType()) { |
||||
questionsEntity.setIsEnable(Constant.IsEnable.NOT_ENABLE.getType()); |
||||
} |
||||
|
||||
if (byId.getIsEnable() == Constant.IsEnable.NOT_ENABLE.getType()) { |
||||
questionsEntity.setIsEnable(Constant.IsEnable.ENABLE.getType()); |
||||
} |
||||
|
||||
return this.updateById(questionsEntity); |
||||
} |
||||
|
||||
@Override |
||||
@Transactional |
||||
public boolean deleteByIds(List<Integer> asList) { |
||||
List<QuestionsEntity> collect = asList.stream().map(item -> { |
||||
QuestionsEntity questionsEntity = new QuestionsEntity(); |
||||
questionsEntity.setId(item); |
||||
questionsEntity.setIsDel(Constant.IsDel.DEL.getType()); |
||||
return questionsEntity; |
||||
}).collect(Collectors.toList()); |
||||
|
||||
return updateBatchById(collect); |
||||
} |
||||
|
||||
/** |
||||
* 校验题干重复和题型不对的,从列表中将该题剔除,名称相同的要去重 |
||||
* |
||||
* @param file |
||||
* @return |
||||
* @throws IOException |
||||
*/ |
||||
@Override |
||||
@Transactional |
||||
public boolean importQuestion(MultipartFile file) throws IOException { |
||||
List<QuestionsImportRequest> list = new ExcelImportUtil(QuestionsImportRequest.class) |
||||
.readExcel(file.getInputStream(), Constant.STARTING_ROW, Constant.STARTING_CELL); |
||||
|
||||
if (list == null || list.size() == 0) { |
||||
ExceptionCast.cast(CommonCode.INVALID_PARAM); |
||||
} |
||||
//List<Person> unique = persons.stream().collect(
|
||||
// Collectors.collectingAndThen(
|
||||
// Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Person::getName))), ArrayList::new)
|
||||
//);
|
||||
|
||||
List<QuestionsEntity> collect = list.stream().map(item -> { |
||||
|
||||
int count = this.count(new QueryWrapper<QuestionsEntity>().eq("question_stem", item.getQuestionStem())); |
||||
if (count > 0) {//说明已存在
|
||||
return null; |
||||
} |
||||
QuestionsEntity questionsEntity = new QuestionsEntity(); |
||||
BeanUtils.copyProperties(item, questionsEntity); |
||||
String questionType = item.getQuestionType(); |
||||
//根据题型名称得到题型号
|
||||
if (questionType.equals(Constant.QuestionType.SINGLE_CHOICE.getDesc())) { |
||||
//单选题
|
||||
questionsEntity.setQuestionTypeNo(Constant.QuestionType.SINGLE_CHOICE.getType()); |
||||
} else if (questionType.equals(Constant.QuestionType.MULTIPLE_CHOICE.getDesc())) { |
||||
//多选题
|
||||
questionsEntity.setQuestionTypeNo(Constant.QuestionType.MULTIPLE_CHOICE.getType()); |
||||
} else if (questionType.equals(Constant.QuestionType.TRUE_OR_FALSE.getDesc())) { |
||||
//判断题
|
||||
questionsEntity.setQuestionTypeNo(Constant.QuestionType.TRUE_OR_FALSE.getType()); |
||||
} else { |
||||
// 题型不正确
|
||||
return null; |
||||
} |
||||
questionsEntity.setCreateTime(new Date()); |
||||
questionsEntity.setModifyTime(new Date()); |
||||
//TODO 创建者和修改者。。。
|
||||
return questionsEntity; |
||||
}).filter(question -> question != null).collect(Collectors.collectingAndThen( |
||||
Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(QuestionsEntity::getQuestionStem))), |
||||
ArrayList::new |
||||
)); |
||||
|
||||
return this.saveBatch(collect); |
||||
} |
||||
|
||||
/** |
||||
* 上传模板文件,修改模板信息表数据 |
||||
* |
||||
* @param file |
||||
* @return |
||||
*/ |
||||
@Override |
||||
@Transactional |
||||
public FilesResult uploadFiles(MultipartFile file) throws IOException { |
||||
FilesResult filesResult = ossService.uploadFiles(file); |
||||
|
||||
XlsxTemplateEntity xlsxTemplateEntity = new XlsxTemplateEntity(); |
||||
BeanUtils.copyProperties(filesResult, xlsxTemplateEntity); |
||||
xlsxTemplateEntity.setId(Constant.XLSX_TEMPLATE_ID); |
||||
xlsxTemplateService.updateById(xlsxTemplateEntity); |
||||
|
||||
return filesResult; |
||||
} |
||||
|
||||
@Override |
||||
public void downloadFiles(HttpServletResponse response) throws IOException { |
||||
XlsxTemplateEntity xlsxTemplate = xlsxTemplateService.getById(Constant.XLSX_TEMPLATE_ID); |
||||
ossService.downloadFiles(response, xlsxTemplate.getFileName()); |
||||
} |
||||
|
||||
@Override |
||||
public EvaluationVO evaluation() { |
||||
|
||||
QueryWrapper<QuestionsEntity> queryWrapper = new QueryWrapper<>(); |
||||
queryWrapper.eq("is_del", Constant.IsDel.NOT_DEL.getType()) //未删除
|
||||
.eq("is_enable", Constant.IsEnable.ENABLE.getType()); //启用
|
||||
|
||||
Set<QuestionsEntity> set = new HashSet<>(); |
||||
|
||||
// 查询测评规则类型
|
||||
EvaluationRulesVO evaluationRules = evaluationRulesService.getEvaluationRules(); |
||||
|
||||
EvaluationVO evaluation = new EvaluationVO(); |
||||
|
||||
BeanUtils.copyProperties(evaluationRules, evaluation); |
||||
|
||||
Integer evaluationType = evaluationRules.getEvaluationType(); |
||||
if (evaluationType == Constant.RulesType.RANDOM.getType()) {//随机
|
||||
// 类型为随机,直接用题目数量
|
||||
Integer questionNum = evaluationRules.getQuestionNum(); |
||||
// 查询题库所有未删除,未禁用的题目id
|
||||
List<QuestionsEntity> questions = this.list(queryWrapper); |
||||
|
||||
set = getRandomList(questionNum, questions); |
||||
|
||||
} else if (evaluationType == Constant.RulesType.CUSTOMIZE.getType()) {//自定义
|
||||
|
||||
int singleNum = 0; |
||||
int multipleNum = 0; |
||||
int judgmentNum = 0; |
||||
|
||||
//判断各条目的题型是否启用
|
||||
if (evaluationRules.getIsSingleEnable() == Constant.IsEnable.ENABLE.getType()) { |
||||
singleNum = evaluationRules.getSingleNum(); |
||||
|
||||
List<QuestionsEntity> singleChoice = this.list(queryWrapper.eq("question_type_no", |
||||
Constant.QuestionType.SINGLE_CHOICE.getType())); |
||||
set.addAll(getRandomList(singleNum, singleChoice)); |
||||
} |
||||
if (evaluationRules.getIsMultipleEnable() == Constant.IsEnable.ENABLE.getType()) { |
||||
multipleNum = evaluationRules.getMultipleNum(); |
||||
|
||||
List<QuestionsEntity> multipleChoice = this.list(queryWrapper.eq("question_type_no", |
||||
Constant.QuestionType.MULTIPLE_CHOICE.getType())); |
||||
|
||||
set.addAll(getRandomList(multipleNum, multipleChoice)); |
||||
} |
||||
if (evaluationRules.getIsJudgmentEnable() == Constant.IsEnable.ENABLE.getType()) { |
||||
judgmentNum = evaluationRules.getJudgmentNum(); |
||||
List<QuestionsEntity> judgments = this.list(queryWrapper.eq("question_type_no", |
||||
Constant.QuestionType.TRUE_OR_FALSE.getType())); |
||||
|
||||
set.addAll(getRandomList(judgmentNum, judgments)); |
||||
} |
||||
|
||||
evaluation.setQuestionNum(singleNum + multipleNum + judgmentNum); |
||||
|
||||
} |
||||
evaluation.setQuestions(set); |
||||
|
||||
return evaluation; |
||||
} |
||||
|
||||
private Set<QuestionsEntity> getRandomList(int len, List<QuestionsEntity> list) { |
||||
Set<QuestionsEntity> set = new HashSet<>(); |
||||
Random random = new Random(); |
||||
int i = 0; |
||||
while (true) { |
||||
i = random.nextInt(list.size()); |
||||
set.add(list.get(i)); |
||||
if (set.size() >= len) { |
||||
break; |
||||
} |
||||
} |
||||
return set; |
||||
} |
||||
} |
@ -0,0 +1,12 @@ |
||||
package com.msdw.tms.service.impl; |
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
||||
import com.msdw.tms.dao.XlsxTemplateDao; |
||||
import com.msdw.tms.entity.XlsxTemplateEntity; |
||||
import com.msdw.tms.service.XlsxTemplateService; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
|
||||
@Service("xlsxTemplateService") |
||||
public class XlsxTemplateServiceImpl extends ServiceImpl<XlsxTemplateDao, XlsxTemplateEntity> implements XlsxTemplateService { |
||||
} |
@ -0,0 +1,6 @@ |
||||
oss.endpoint=oss-cn-shenzhen.aliyuncs.com |
||||
oss.accessKeyId=LTAIHIkGqaILObBm |
||||
oss.secretAccessKey=QDTxKMrfDPeJ3bsr3AqjYHwnlL6PdM |
||||
oss.bucketName=liuwanr |
||||
oss.sufferUrl=http://liuwanr.oss-cn-shenzhen.aliyuncs.com/ |
||||
user.userAvatars=userAvatars |
@ -0,0 +1,15 @@ |
||||
spring: |
||||
datasource: |
||||
url: jdbc:mysql://www.liuwanr.cn:3306/msdw_tms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai |
||||
username: super |
||||
password: huoran888 |
||||
driver-class-name: com.mysql.jdbc.Driver |
||||
mybatis-plus: |
||||
configuration: |
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用 |
||||
mapper-locations: classpath:/mapper/**/*.xml |
||||
global-config: |
||||
db-config: |
||||
id-type: auto |
||||
server: |
||||
port: 7000 |
Binary file not shown.
@ -0,0 +1,47 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<configuration> |
||||
<!--定义日志文件的存储地址,使用绝对路径--> |
||||
<property name="LOG_HOME" value="d:/logs/tms"/> |
||||
|
||||
<!-- Console 输出设置 --> |
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> |
||||
<encoder> |
||||
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--> |
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> |
||||
<charset>utf8</charset> |
||||
</encoder> |
||||
</appender> |
||||
|
||||
<!-- 按照每天生成日志文件 --> |
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> |
||||
<!--日志文件输出的文件名--> |
||||
<fileNamePattern>${LOG_HOME}/tms.%d{yyyy-MM-dd}.log</fileNamePattern> |
||||
</rollingPolicy> |
||||
<encoder> |
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> |
||||
</encoder> |
||||
</appender> |
||||
|
||||
<!-- 异步输出 --> |
||||
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender"> |
||||
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 --> |
||||
<discardingThreshold>0</discardingThreshold> |
||||
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 --> |
||||
<queueSize>512</queueSize> |
||||
<!-- 添加附加的appender,最多只能添加一个 --> |
||||
<appender-ref ref="FILE"/> |
||||
</appender> |
||||
|
||||
|
||||
<logger name="org.apache.ibatis.cache.decorators.LoggingCache" level="DEBUG" additivity="false"> |
||||
<appender-ref ref="CONSOLE"/> |
||||
</logger> |
||||
<logger name="org.springframework.boot" level="DEBUG"/> |
||||
<root level="info"> |
||||
<!--<appender-ref ref="ASYNC"/>--> |
||||
<appender-ref ref="FILE"/> |
||||
<appender-ref ref="CONSOLE"/> |
||||
</root> |
||||
</configuration> |
@ -0,0 +1,21 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
|
||||
<mapper namespace="com.msdw.tms.dao.EvaluationRulesDao"> |
||||
|
||||
<!-- 可根据自己的需求,是否要使用 --> |
||||
<resultMap type="com.msdw.tms.entity.EvaluationRulesEntity" id="evaluationRulesMap"> |
||||
<result property="id" column="id"/> |
||||
<result property="evaluationType" column="evaluation_type"/> |
||||
<result property="duration" column="duration"/> |
||||
<result property="questionNum" column="question_num"/> |
||||
<result property="singleNum" column="single_num"/> |
||||
<result property="isSingleEnable" column="is_single_enable"/> |
||||
<result property="multipleNum" column="multiple_num"/> |
||||
<result property="isMultipleEnable" column="is_multiple_enable"/> |
||||
<result property="judgmentNum" column="judgment_num"/> |
||||
<result property="isJudgmentEnable" column="is_judgment_enable"/> |
||||
</resultMap> |
||||
|
||||
|
||||
</mapper> |
@ -0,0 +1,30 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
|
||||
<mapper namespace="com.msdw.tms.dao.QuestionsDao"> |
||||
|
||||
<!-- 可根据自己的需求,是否要使用 --> |
||||
<resultMap type="com.msdw.tms.entity.QuestionsEntity" id="questionsMap"> |
||||
<result property="id" column="id"/> |
||||
<result property="questionTypeNo" column="question_type_no"/> |
||||
<result property="questionType" column="question_type"/> |
||||
<result property="questionStem" column="question_stem"/> |
||||
<result property="optionA" column="option_a"/> |
||||
<result property="optionB" column="option_b"/> |
||||
<result property="optionC" column="option_c"/> |
||||
<result property="optionD" column="option_d"/> |
||||
<result property="optionE" column="option_e"/> |
||||
<result property="optionF" column="option_f"/> |
||||
<result property="answer" column="answer"/> |
||||
<result property="answerAnalysis" column="answer_analysis"/> |
||||
<result property="isEnable" column="is_enable"/> |
||||
<result property="isDel" column="is_del"/> |
||||
<result property="createUser" column="create_user"/> |
||||
<result property="createTime" column="create_time"/> |
||||
<result property="modifyUser" column="modify_user"/> |
||||
<result property="modifyTime" column="modify_time"/> |
||||
<result property="subjects" column="subjects"/> |
||||
</resultMap> |
||||
|
||||
|
||||
</mapper> |
@ -0,0 +1,15 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
|
||||
<mapper namespace="com.msdw.tms.dao.XlsxTemplateDao"> |
||||
|
||||
<!-- 可根据自己的需求,是否要使用 --> |
||||
<resultMap type="com.msdw.tms.entity.XlsxTemplateEntity" id="xlsxTemplateMap"> |
||||
<result property="id" column="id"/> |
||||
<result property="fileName" column="file_name"/> |
||||
<result property="fileUrl" column="file_url"/> |
||||
<result property="status" column="status"/> |
||||
</resultMap> |
||||
|
||||
|
||||
</mapper> |
@ -0,0 +1,13 @@ |
||||
package com.msdw.tms; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
import org.springframework.boot.test.context.SpringBootTest; |
||||
|
||||
@SpringBootTest |
||||
class TmsApplicationTests { |
||||
|
||||
@Test |
||||
void contextLoads() { |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue